@h-rig/cli 0.0.6-alpha.1 → 0.0.6-alpha.3

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.
@@ -2,8 +2,8 @@
2
2
  var __require = import.meta.require;
3
3
 
4
4
  // packages/cli/src/commands/setup.ts
5
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync, writeFileSync as writeFileSync2 } from "fs";
6
- import { resolve as resolve5 } from "path";
5
+ import { existsSync as existsSync5, mkdirSync as mkdirSync2, readdirSync, writeFileSync as writeFileSync2 } from "fs";
6
+ import { resolve as resolve6 } from "path";
7
7
 
8
8
  // packages/cli/src/runner.ts
9
9
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
@@ -171,8 +171,8 @@ async function buildPiSetupChecks(input = {}) {
171
171
  }
172
172
 
173
173
  // packages/cli/src/commands/_doctor-checks.ts
174
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
175
- import { resolve as resolve4 } from "path";
174
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
175
+ import { resolve as resolve5 } from "path";
176
176
  import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/control-plane/setup-version";
177
177
 
178
178
  // packages/cli/src/commands/_connection-state.ts
@@ -259,15 +259,33 @@ function resolveSelectedConnection(projectRoot, options = {}) {
259
259
 
260
260
  // packages/cli/src/commands/_server-client.ts
261
261
  import { spawnSync } from "child_process";
262
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
263
+ import { resolve as resolve4 } from "path";
262
264
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
263
265
  var cachedGitHubBearerToken;
264
266
  function cleanToken(value) {
265
267
  const trimmed = value?.trim();
266
268
  return trimmed ? trimmed : null;
267
269
  }
268
- function readGitHubBearerTokenForRemote() {
270
+ function readPrivateRemoteSessionToken(projectRoot) {
271
+ const path = resolve4(projectRoot, ".rig", "state", "github-auth.json");
272
+ if (!existsSync3(path))
273
+ return null;
274
+ try {
275
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
276
+ return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
277
+ } catch {
278
+ return null;
279
+ }
280
+ }
281
+ function readGitHubBearerTokenForRemote(projectRoot) {
269
282
  if (cachedGitHubBearerToken !== undefined)
270
283
  return cachedGitHubBearerToken;
284
+ const privateSession = readPrivateRemoteSessionToken(projectRoot);
285
+ if (privateSession) {
286
+ cachedGitHubBearerToken = privateSession;
287
+ return cachedGitHubBearerToken;
288
+ }
271
289
  const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
272
290
  if (envToken) {
273
291
  cachedGitHubBearerToken = envToken;
@@ -287,7 +305,7 @@ async function ensureServerForCli(projectRoot) {
287
305
  if (selected?.connection.kind === "remote") {
288
306
  return {
289
307
  baseUrl: selected.connection.baseUrl,
290
- authToken: readGitHubBearerTokenForRemote(),
308
+ authToken: readGitHubBearerTokenForRemote(projectRoot),
291
309
  connectionKind: "remote"
292
310
  };
293
311
  }
@@ -387,11 +405,11 @@ function repoSlugFromConfig(config) {
387
405
  function loadFallbackConfig(projectRoot) {
388
406
  const candidates = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
389
407
  for (const name of candidates) {
390
- const path = resolve4(projectRoot, name);
391
- if (!existsSync3(path))
408
+ const path = resolve5(projectRoot, name);
409
+ if (!existsSync4(path))
392
410
  continue;
393
411
  try {
394
- const source = readFileSync3(path, "utf8");
412
+ const source = readFileSync4(path, "utf8");
395
413
  if (name.endsWith(".json"))
396
414
  return JSON.parse(source);
397
415
  const owner = source.match(/owner\s*:\s*["']([^"']+)["']/)?.[1];
@@ -470,7 +488,7 @@ async function runRigDoctorChecks(options) {
470
488
  checks.push(check("bun", `bun >= ${MIN_SUPPORTED_BUN_VERSION}`, isSupportedBunVersion(bunVersion) ? "pass" : "fail", `found ${bunVersion}`, `Install Bun ${MIN_SUPPORTED_BUN_VERSION} or newer.`), check("git", "git", which("git") ? "pass" : "fail", which("git") ?? undefined, "Install git and ensure it is on PATH."), check("jq", "jq", which("jq") ? "pass" : "warn", which("jq") ?? undefined, "Install jq (for example `brew install jq`)."));
471
489
  const loadedConfig = await loadConfig(projectRoot).catch(() => null);
472
490
  const config = loadedConfig ?? loadFallbackConfig(projectRoot);
473
- const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync3(resolve4(projectRoot, name)));
491
+ const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync4(resolve5(projectRoot, name)));
474
492
  checks.push(config ? check("config", "rig.config loadable", "pass") : check("config", "rig.config loadable", hasConfigFile ? "fail" : "fail", hasConfigFile ? "config file exists but failed to load" : "missing rig.config.ts/json", "Run `rig init` or fix the config error."));
475
493
  const taskSourceKind = config?.taskSource?.kind;
476
494
  checks.push(taskSourceKind ? check("task-source", "task source configured", "pass", taskSourceKind) : check("task-source", "task source configured", "fail", "missing taskSource", "Configure taskSource in rig.config.ts."));
@@ -638,8 +656,8 @@ function runSetupInit(projectRoot) {
638
656
  mkdirSync2(stateDir, { recursive: true });
639
657
  mkdirSync2(logsDir, { recursive: true });
640
658
  mkdirSync2(artifactsDir, { recursive: true });
641
- const failuresPath = resolve5(stateDir, "failed_approaches.md");
642
- if (!existsSync4(failuresPath)) {
659
+ const failuresPath = resolve6(stateDir, "failed_approaches.md");
660
+ if (!existsSync5(failuresPath)) {
643
661
  writeFileSync2(failuresPath, `# Failed Approaches
644
662
 
645
663
  `, "utf-8");
@@ -657,18 +675,18 @@ async function runSetupCheck(projectRoot) {
657
675
  }
658
676
  async function runSetupPreflight(projectRoot) {
659
677
  await runSetupCheck(projectRoot);
660
- const validationRoot = resolve5(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
661
- if (existsSync4(validationRoot)) {
678
+ const validationRoot = resolve6(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
679
+ if (existsSync5(validationRoot)) {
662
680
  const validators = readdirSync(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
663
681
  for (const validator of validators) {
664
- const script = resolve5(validationRoot, validator.name, "validate.sh");
665
- if (existsSync4(script)) {
682
+ const script = resolve6(validationRoot, validator.name, "validate.sh");
683
+ if (existsSync5(script)) {
666
684
  console.log(`OK: validator script ${script}`);
667
685
  }
668
686
  }
669
687
  }
670
- const hooksRoot = resolve5(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
671
- if (existsSync4(hooksRoot)) {
688
+ const hooksRoot = resolve6(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
689
+ if (existsSync5(hooksRoot)) {
672
690
  const hooks = readdirSync(hooksRoot).filter((name) => name.endsWith(".sh"));
673
691
  for (const hook of hooks) {
674
692
  console.log(`OK: hook ${hook}`);
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // packages/cli/src/commands/task-run-driver.ts
3
- import { copyFileSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, statSync } from "fs";
3
+ import { copyFileSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, statSync, writeFileSync } from "fs";
4
4
  import { resolve as resolve4 } from "path";
5
5
  import { spawn, spawnSync } from "child_process";
6
6
  import { createInterface as createLineInterface } from "readline";
@@ -405,7 +405,24 @@ var PI_CANONICAL_RUN_STAGES = [
405
405
  function canonicalPiRunStages() {
406
406
  return [...PI_CANONICAL_RUN_STAGES];
407
407
  }
408
+ function looksLikeGitHubToken(value) {
409
+ const token = value?.trim();
410
+ if (!token)
411
+ return false;
412
+ return /^(gh[opusr]_|github_pat_)/.test(token);
413
+ }
414
+ function githubBridgeEnv(token) {
415
+ const clean = token?.trim();
416
+ if (!clean)
417
+ return {};
418
+ return {
419
+ RIG_GITHUB_TOKEN: clean,
420
+ GITHUB_TOKEN: clean,
421
+ GH_TOKEN: clean
422
+ };
423
+ }
408
424
  function buildPiRigBridgeEnv(input) {
425
+ const githubToken = input.githubToken?.trim() || (looksLikeGitHubToken(input.authToken) ? input.authToken.trim() : "");
409
426
  return {
410
427
  RIG_PROJECT_ROOT: input.projectRoot,
411
428
  PROJECT_RIG_ROOT: input.projectRoot,
@@ -415,7 +432,7 @@ function buildPiRigBridgeEnv(input) {
415
432
  RIG_RUNTIME_ADAPTER: "pi",
416
433
  ...input.serverUrl ? { RIG_SERVER_URL: input.serverUrl } : {},
417
434
  ...input.authToken ? { RIG_AUTH_TOKEN: input.authToken } : {},
418
- ...input.githubToken ? { RIG_GITHUB_TOKEN: input.githubToken } : {}
435
+ ...githubBridgeEnv(githubToken)
419
436
  };
420
437
  }
421
438
  function runGitSync(cwd, args, input) {
@@ -476,6 +493,14 @@ function buildTaskRunReviewEnv(config) {
476
493
  ...review?.provider ? { AI_REVIEW_PROVIDER: review.provider } : {}
477
494
  };
478
495
  }
496
+ function buildDirtyBaselineHandshakeEnv(input) {
497
+ if (input.baselineMode !== "dirty-snapshot")
498
+ return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
499
+ return {
500
+ RIG_BASELINE_MODE: "dirty-snapshot",
501
+ RIG_DIRTY_BASELINE_READY_FILE: resolve4(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
502
+ };
503
+ }
479
504
  function positiveInt(value, fallback) {
480
505
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
481
506
  }
@@ -1057,7 +1082,7 @@ function stringArrayField(record, key) {
1057
1082
  async function executeRigOwnedTaskRun(context, input) {
1058
1083
  const runtimeTaskId = input.taskId?.trim() || `adhoc-${input.runId}`;
1059
1084
  const sourceTask = readRunSourceTaskContract(context.projectRoot, input.runId, input.taskId);
1060
- const prompt = buildRunPrompt({
1085
+ let prompt = buildRunPrompt({
1061
1086
  projectRoot: context.projectRoot,
1062
1087
  taskId: input.taskId,
1063
1088
  fallbackTitle: input.title,
@@ -1157,7 +1182,22 @@ async function executeRigOwnedTaskRun(context, input) {
1157
1182
  const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
1158
1183
  const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
1159
1184
  const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
1160
- patchAuthorityRun(context.projectRoot, input.runId, { planning: planningClassification });
1185
+ const planningArtifactPath = resolve4("artifacts", runtimeTaskId, "implementation-plan.md");
1186
+ const persistedPlanning = {
1187
+ ...planningClassification,
1188
+ classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
1189
+ artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
1190
+ classifiedAt: new Date().toISOString()
1191
+ };
1192
+ mkdirSync(resolve4(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
1193
+ writeFileSync(resolve4(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
1194
+ `, "utf8");
1195
+ patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
1196
+ prompt = `${prompt}
1197
+
1198
+ Rig planning classification:
1199
+ ${JSON.stringify(persistedPlanning, null, 2)}
1200
+ ${planningClassification.planningRequired ? `Before implementing, write a concise implementation plan to ${planningArtifactPath}. Treat that plan artifact as required acceptance evidence for the Plan stage.` : "Planning is not required for this run; briefly state why before implementation."}`;
1161
1201
  if (input.runtimeAdapter === "pi") {
1162
1202
  for (const stage of ["Connect", "GitHub/task sync", "Prepare workspace", "Launch Pi", "Plan", "Implement"]) {
1163
1203
  appendPiStageLog({
@@ -1224,6 +1264,7 @@ async function executeRigOwnedTaskRun(context, input) {
1224
1264
  ...sourceTask ? { RIG_SOURCE_TASK_JSON: JSON.stringify(sourceTask) } : {}
1225
1265
  };
1226
1266
  Object.assign(childEnv, buildTaskRunReviewEnv(automationConfig));
1267
+ Object.assign(childEnv, buildDirtyBaselineHandshakeEnv({ projectRoot: context.projectRoot, runId: input.runId, baselineMode: input.baselineMode }));
1227
1268
  const automationLimits = resolveTaskRunAutomationLimits(automationConfig);
1228
1269
  const maxAttempts = automationLimits.maxValidationAttempts;
1229
1270
  const promoteToValidating = (detail) => {
@@ -1287,13 +1328,20 @@ async function executeRigOwnedTaskRun(context, input) {
1287
1328
  if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
1288
1329
  dirtyBaselineApplied = true;
1289
1330
  const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
1331
+ const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
1332
+ if (readyFile) {
1333
+ mkdirSync(resolve4(readyFile, ".."), { recursive: true });
1334
+ writeFileSync(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
1335
+ `, "utf8");
1336
+ }
1290
1337
  appendRunLog(context.projectRoot, input.runId, {
1291
1338
  id: `log:${input.runId}:dirty-baseline`,
1292
1339
  title: "Dirty baseline snapshot",
1293
1340
  detail: dirty.detail,
1294
1341
  tone: dirty.applied ? "tool" : "info",
1295
1342
  status: dirty.applied ? "completed" : "skipped",
1296
- createdAt: new Date().toISOString()
1343
+ createdAt: new Date().toISOString(),
1344
+ payload: readyFile ? { readyFile } : undefined
1297
1345
  });
1298
1346
  emitServerRunEvent({ type: "log", runId: input.runId, title: "Dirty baseline snapshot" });
1299
1347
  }
@@ -1765,6 +1813,29 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
1765
1813
  });
1766
1814
  throw new CliError2(terminalFailureDetail, exit.code ?? 1);
1767
1815
  }
1816
+ if (planningClassification.planningRequired) {
1817
+ const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
1818
+ const expectedPlanPath = resolve4(planWorkspace, planningArtifactPath);
1819
+ if (!existsSync2(expectedPlanPath)) {
1820
+ const failedAt = new Date().toISOString();
1821
+ const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
1822
+ patchAuthorityRun(context.projectRoot, input.runId, {
1823
+ status: "needs_attention",
1824
+ completedAt: failedAt,
1825
+ errorText: failureDetail
1826
+ });
1827
+ appendRunLog(context.projectRoot, input.runId, {
1828
+ id: `log:${input.runId}:plan-artifact-missing`,
1829
+ title: "Required plan artifact missing",
1830
+ detail: failureDetail,
1831
+ tone: "error",
1832
+ status: "needs_attention",
1833
+ createdAt: failedAt
1834
+ });
1835
+ emitServerRunEvent({ type: "failed", runId: input.runId, error: failureDetail });
1836
+ throw new CliError2(failureDetail, 1);
1837
+ }
1838
+ }
1768
1839
  const runPiPrFeedbackFix = async (message) => {
1769
1840
  appendPiStageLog({
1770
1841
  projectRoot: context.projectRoot,
@@ -1935,5 +2006,6 @@ export {
1935
2006
  buildTaskRunReviewEnv,
1936
2007
  buildPiValidationRetrySteeringPrompt,
1937
2008
  buildPiRigBridgeEnv,
2009
+ buildDirtyBaselineHandshakeEnv,
1938
2010
  applyDirtyBaselineSnapshot
1939
2011
  };
@@ -1,9 +1,9 @@
1
1
  // @bun
2
2
  // packages/cli/src/commands/task.ts
3
- import { readFileSync as readFileSync3 } from "fs";
3
+ import { readFileSync as readFileSync4 } from "fs";
4
4
  import { spawnSync as spawnSync2 } from "child_process";
5
5
  import { createInterface as createInterface3 } from "readline/promises";
6
- import { resolve as resolve3 } from "path";
6
+ import { resolve as resolve4 } from "path";
7
7
 
8
8
  // packages/cli/src/runner.ts
9
9
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
@@ -189,15 +189,33 @@ function resolveSelectedConnection(projectRoot, options = {}) {
189
189
 
190
190
  // packages/cli/src/commands/_server-client.ts
191
191
  import { spawnSync } from "child_process";
192
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
193
+ import { resolve as resolve2 } from "path";
192
194
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
193
195
  var cachedGitHubBearerToken;
194
196
  function cleanToken(value) {
195
197
  const trimmed = value?.trim();
196
198
  return trimmed ? trimmed : null;
197
199
  }
198
- function readGitHubBearerTokenForRemote() {
200
+ function readPrivateRemoteSessionToken(projectRoot) {
201
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
202
+ if (!existsSync2(path))
203
+ return null;
204
+ try {
205
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
206
+ return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
207
+ } catch {
208
+ return null;
209
+ }
210
+ }
211
+ function readGitHubBearerTokenForRemote(projectRoot) {
199
212
  if (cachedGitHubBearerToken !== undefined)
200
213
  return cachedGitHubBearerToken;
214
+ const privateSession = readPrivateRemoteSessionToken(projectRoot);
215
+ if (privateSession) {
216
+ cachedGitHubBearerToken = privateSession;
217
+ return cachedGitHubBearerToken;
218
+ }
201
219
  const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
202
220
  if (envToken) {
203
221
  cachedGitHubBearerToken = envToken;
@@ -217,7 +235,7 @@ async function ensureServerForCli(projectRoot) {
217
235
  if (selected?.connection.kind === "remote") {
218
236
  return {
219
237
  baseUrl: selected.connection.baseUrl,
220
- authToken: readGitHubBearerTokenForRemote(),
238
+ authToken: readGitHubBearerTokenForRemote(projectRoot),
221
239
  connectionKind: "remote"
222
240
  };
223
241
  }
@@ -378,9 +396,9 @@ async function submitTaskRunViaServer(context, input) {
378
396
  }
379
397
 
380
398
  // packages/cli/src/commands/_pi-install.ts
381
- import { existsSync as existsSync2, readFileSync as readFileSync2, rmSync } from "fs";
399
+ import { existsSync as existsSync3, readFileSync as readFileSync3, rmSync } from "fs";
382
400
  import { homedir as homedir2 } from "os";
383
- import { resolve as resolve2 } from "path";
401
+ import { resolve as resolve3 } from "path";
384
402
  var PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
385
403
  async function defaultCommandRunner(command, options = {}) {
386
404
  const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
@@ -392,7 +410,7 @@ async function defaultCommandRunner(command, options = {}) {
392
410
  return { exitCode, stdout, stderr };
393
411
  }
394
412
  function resolvePiRigExtensionPath(homeDir) {
395
- return resolve2(homeDir, ".pi", "agent", "extensions", "pi-rig");
413
+ return resolve3(homeDir, ".pi", "agent", "extensions", "pi-rig");
396
414
  }
397
415
  function resolvePiHomeDir(inputHomeDir) {
398
416
  return inputHomeDir ?? process.env.RIG_PI_HOME_DIR?.trim() ?? homedir2();
@@ -420,13 +438,13 @@ async function checkPiRigInstall(input = {}) {
420
438
  piRig: { ok: true, label: "pi-rig global extension", detail: extensionPath }
421
439
  };
422
440
  }
423
- const exists = input.exists ?? existsSync2;
441
+ const exists = input.exists ?? existsSync3;
424
442
  const runner = input.commandRunner ?? defaultCommandRunner;
425
443
  const piResult = await safeRun(runner, ["pi", "--version"]);
426
444
  const piListResult = piResult.exitCode === 0 ? await safeRun(runner, ["pi", "list"]) : { exitCode: 1, stdout: "", stderr: "" };
427
445
  const listedPiRig = piListResult.exitCode === 0 && piListContainsPiRig(`${piListResult.stdout}
428
446
  ${piListResult.stderr}`);
429
- const legacyBridge = exists(resolve2(extensionPath, "index.ts"));
447
+ const legacyBridge = exists(resolve3(extensionPath, "index.ts"));
430
448
  const hasPiRig = listedPiRig;
431
449
  return {
432
450
  extensionPath,
@@ -1101,7 +1119,7 @@ async function executeTask(context, args, options) {
1101
1119
  const fileFlag = takeOption(rest.slice(1), "--file");
1102
1120
  let content;
1103
1121
  if (fileFlag.value) {
1104
- content = readFileSync3(resolve3(context.projectRoot, fileFlag.value), "utf-8");
1122
+ content = readFileSync4(resolve4(context.projectRoot, fileFlag.value), "utf-8");
1105
1123
  } else {
1106
1124
  content = await readStdin();
1107
1125
  }