agentplane 0.1.3 → 0.1.4

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/README.md CHANGED
@@ -5,53 +5,83 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/basilisk-labs/agentplane/blob/main/LICENSE)
6
6
  [![Node.js 20+](https://img.shields.io/badge/Node.js-20%2B-3c873a.svg)](https://github.com/basilisk-labs/agentplane/blob/main/docs/user/prerequisites.mdx)
7
7
 
8
- Agent Plane is an offline-first CLI for running policy-driven agent workflows inside real repositories.
9
- It turns "AI magic" into a predictable process with approvals, role boundaries, and audit-friendly artifacts.
8
+ Agent Plane is a policy-driven framework for running LLM agents inside real repositories. It turns "AI magic" into an engineering process: explicit approvals, role boundaries, and a reproducible execution pipeline. The goal is simple: make agents boring, safe, and auditable.
10
9
 
11
- ## Features
10
+ ## Why Agent Plane
12
11
 
13
- - Policy-first execution with explicit approvals and guardrails.
14
- - Role-based workflows for teams: ORCHESTRATOR, PLANNER, CREATOR, INTEGRATOR, etc.
15
- - Two workflow modes: `direct` (single checkout) and `branch_pr` (worktrees + integration).
16
- - Task tracking, verification, and exports baked in.
17
- - Recipes for repeatable setup and automation.
12
+ - You want agents that behave predictably inside real repos.
13
+ - You need human approvals, clear roles, and traceable artifacts.
14
+ - You want guardrails by default, not optional add-ons.
15
+ - You want an offline-first CLI that keeps state local and inspectable.
18
16
 
19
- ## Install
17
+ ## 5-minute start
18
+
19
+ Install and initialize the CLI:
20
20
 
21
21
  ```bash
22
22
  npm install -g agentplane
23
+ agentplane init
24
+ agentplane quickstart
23
25
  ```
24
26
 
25
- Or run without installing:
27
+ Create your first task and run the workflow:
26
28
 
27
29
  ```bash
28
- npx agentplane --help
30
+ agentplane task new --title "First task" --description "Describe the change" --priority med --owner ORCHESTRATOR --tag docs
31
+ agentplane verify <task-id>
32
+ agentplane finish <task-id>
29
33
  ```
30
34
 
31
- ## Requirements
35
+ Prefer `npx` instead of a global install?
32
36
 
33
- - Node.js >= 20
37
+ ```bash
38
+ npx agentplane init
39
+ npx agentplane quickstart
40
+ ```
34
41
 
35
- ## Quickstart
42
+ ## What gets installed automatically
36
43
 
37
- Initialize a repository:
44
+ - `.agentplane/` is created with config, tasks, agents, and caches.
45
+ - `AGENTS.md` is created if missing and defines the policy/guardrails.
46
+ - Built-in agent definitions are copied into `.agentplane/agents/`.
47
+ - Optional recipes can install additional agents when you run `agentplane recipes install ...`.
38
48
 
39
- ```bash
40
- npx agentplane init
49
+ ## Guardrails and artifacts
50
+
51
+ - Approval gates for plans and network access (configured in `.agentplane/config.json`).
52
+ - Role boundaries (ORCHESTRATOR, PLANNER, CODER, INTEGRATOR, etc.).
53
+ - Agent definitions in `.agentplane/agents/`.
54
+ - Task records in `.agentplane/tasks/` with a snapshot export in `.agentplane/tasks.json`.
55
+ - A visible, reproducible pipeline:
56
+
57
+ ```text
58
+ Preflight -> Plan -> Approval -> Tasks -> Verify -> Finish -> Export
41
59
  ```
42
60
 
43
- See the built-in quickstart guide:
61
+ ## Features
62
+
63
+ - Policy-first execution with explicit approvals and guardrails.
64
+ - Role-based workflows for teams: ORCHESTRATOR, PLANNER, CREATOR, INTEGRATOR, etc.
65
+ - Two workflow modes: `direct` (single checkout) and `branch_pr` (worktrees + integration).
66
+ - Task tracking, verification, and exports baked in.
67
+ - Recipes for repeatable setup and automation.
68
+
69
+ ## Install
44
70
 
45
71
  ```bash
46
- npx agentplane quickstart
72
+ npm install -g agentplane
47
73
  ```
48
74
 
49
- Switch workflow mode if you need a structured team flow:
75
+ Or run without installing:
50
76
 
51
77
  ```bash
52
- npx agentplane config set workflow_mode branch_pr
78
+ npx agentplane --help
53
79
  ```
54
80
 
81
+ ## Requirements
82
+
83
+ - Node.js >= 20
84
+
55
85
  ## Common Commands
56
86
 
57
87
  ```bash
@@ -73,15 +103,6 @@ agentplane recipes list
73
103
  - Project layout: https://github.com/basilisk-labs/agentplane/blob/main/docs/developer/project-layout.mdx
74
104
  - Recipes: https://github.com/basilisk-labs/agentplane/tree/main/agentplane-recipes
75
105
 
76
- ## How it works
77
-
78
- Agent Plane expects a repository policy file (`AGENTS.md`) plus a project config (`.agentplane/config.json`).
79
- Together, they define role boundaries, approval gates, and the execution pipeline:
80
-
81
- ```text
82
- Preflight -> Plan -> Approval -> Tasks -> Verify -> Finish -> Export
83
- ```
84
-
85
106
  ## Support
86
107
 
87
108
  - Issues: https://github.com/basilisk-labs/agentplane/issues
@@ -1 +1 @@
1
- {"version":3,"file":"run-cli.d.ts","sourceRoot":"","sources":["../src/run-cli.ts"],"names":[],"mappings":"AAo8QA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4/D5D"}
1
+ {"version":3,"file":"run-cli.d.ts","sourceRoot":"","sources":["../src/run-cli.ts"],"names":[],"mappings":"AA69QA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4/D5D"}
package/dist/run-cli.js CHANGED
@@ -437,7 +437,7 @@ const BRANCH_STATUS_USAGE_EXAMPLE = "agentplane branch status --base main";
437
437
  const BRANCH_REMOVE_USAGE = "Usage: agentplane branch remove [--branch <name>] [--worktree <path>] [--force] [--quiet]";
438
438
  const BRANCH_REMOVE_USAGE_EXAMPLE = "agentplane branch remove --branch task/20260203-F1Q8AB --worktree .agentplane/worktrees/task";
439
439
  const UPGRADE_USAGE = "Usage: agentplane upgrade [--tag <tag>] [--dry-run] [--no-backup] [--source <repo-url>] [--bundle <path|url>] [--checksum <path|url>]";
440
- const UPGRADE_USAGE_EXAMPLE = "agentplane upgrade --tag v0.1.3 --dry-run";
440
+ const UPGRADE_USAGE_EXAMPLE = "agentplane upgrade --tag v0.1.4 --dry-run";
441
441
  const INIT_USAGE = "Usage: agentplane init --ide <...> --workflow <...> --hooks <...> --require-plan-approval <...> --require-network-approval <...> [--recipes <...>] [--yes] [--force|--backup]";
442
442
  const INIT_USAGE_EXAMPLE = "agentplane init --ide codex --workflow direct --hooks false --require-plan-approval true --require-network-approval true --yes";
443
443
  const CONFIG_SET_USAGE = "Usage: agentplane config set <key> <value>";
@@ -3016,7 +3016,7 @@ async function cmdTaskNew(opts) {
3016
3016
  comments: [],
3017
3017
  doc_version: 2,
3018
3018
  doc_updated_at: nowIso(),
3019
- doc_updated_by: "agentplane",
3019
+ doc_updated_by: flags.owner,
3020
3020
  id_source: "generated",
3021
3021
  };
3022
3022
  if (requiresVerify(flags.tags, config.tasks.verify.required_tags) &&
@@ -3149,6 +3149,7 @@ async function cmdTaskAdd(opts) {
3149
3149
  const tags = dedupeStrings(flags.tags);
3150
3150
  const dependsOn = dedupeStrings(flags.dependsOn);
3151
3151
  const verify = dedupeStrings(flags.verify);
3152
+ const docUpdatedBy = (flags.commentAuthor ?? "").trim() || flags.owner;
3152
3153
  if (requiresVerify(tags, config.tasks.verify.required_tags) && verify.length === 0) {
3153
3154
  throw new CliError({
3154
3155
  exitCode: 2,
@@ -3171,7 +3172,7 @@ async function cmdTaskAdd(opts) {
3171
3172
  : [],
3172
3173
  doc_version: 2,
3173
3174
  doc_updated_at: nowIso(),
3174
- doc_updated_by: "agentplane",
3175
+ doc_updated_by: docUpdatedBy,
3175
3176
  id_source: "explicit",
3176
3177
  }));
3177
3178
  if (backend.writeTasks) {
@@ -3844,10 +3845,15 @@ async function cmdTaskScaffold(opts) {
3844
3845
  comments: [],
3845
3846
  doc_version: 2,
3846
3847
  doc_updated_at: nowIso(),
3847
- doc_updated_by: "agentplane",
3848
+ doc_updated_by: "UNKNOWN",
3848
3849
  };
3849
3850
  if (flags.title)
3850
3851
  baseTask.title = flags.title;
3852
+ if (typeof baseTask.doc_updated_by !== "string" ||
3853
+ baseTask.doc_updated_by.trim().length === 0 ||
3854
+ baseTask.doc_updated_by.trim().toLowerCase() === "agentplane") {
3855
+ baseTask.doc_updated_by = baseTask.owner?.trim() ? baseTask.owner : "UNKNOWN";
3856
+ }
3851
3857
  const frontmatter = taskDataToFrontmatter(baseTask);
3852
3858
  const body = ensureDocSections("", config.tasks.doc.required_sections);
3853
3859
  const text = renderTaskReadme(frontmatter, body);
@@ -3983,7 +3989,7 @@ async function cmdTaskComment(opts) {
3983
3989
  comments: [...existing, { author: opts.author, body: opts.body }],
3984
3990
  doc_version: 2,
3985
3991
  doc_updated_at: nowIso(),
3986
- doc_updated_by: "agentplane",
3992
+ doc_updated_by: opts.author,
3987
3993
  };
3988
3994
  await backend.writeTask(next);
3989
3995
  process.stdout.write(`${successMessage("commented", opts.taskId)}\n`);
@@ -4086,7 +4092,7 @@ async function cmdTaskSetStatus(opts) {
4086
4092
  comments,
4087
4093
  doc_version: 2,
4088
4094
  doc_updated_at: nowIso(),
4089
- doc_updated_by: "agentplane",
4095
+ doc_updated_by: resolveDocUpdatedBy(task, opts.author),
4090
4096
  };
4091
4097
  if (opts.commit) {
4092
4098
  const commitInfo = await readCommitInfo(resolved.gitRoot, opts.commit);
@@ -5365,7 +5371,7 @@ async function cmdStart(opts) {
5365
5371
  comments: commentsValue,
5366
5372
  doc_version: 2,
5367
5373
  doc_updated_at: nowIso(),
5368
- doc_updated_by: "agentplane",
5374
+ doc_updated_by: opts.author,
5369
5375
  };
5370
5376
  await backend.writeTask(nextTask);
5371
5377
  let commitInfo = null;
@@ -5441,7 +5447,7 @@ async function cmdBlock(opts) {
5441
5447
  comments: commentsValue,
5442
5448
  doc_version: 2,
5443
5449
  doc_updated_at: nowIso(),
5444
- doc_updated_by: "agentplane",
5450
+ doc_updated_by: opts.author,
5445
5451
  };
5446
5452
  await backend.writeTask(nextTask);
5447
5453
  let commitInfo = null;
@@ -5542,7 +5548,7 @@ async function cmdFinish(opts) {
5542
5548
  comments: commentsValue,
5543
5549
  doc_version: 2,
5544
5550
  doc_updated_at: nowIso(),
5545
- doc_updated_by: "agentplane",
5551
+ doc_updated_by: opts.author,
5546
5552
  };
5547
5553
  await backend.writeTask(nextTask);
5548
5554
  }
@@ -7071,6 +7077,23 @@ function setMarkdownSection(body, section, text) {
7071
7077
  function normalizeDocSectionName(section) {
7072
7078
  return section.trim().replaceAll(/\s+/g, " ").toLowerCase();
7073
7079
  }
7080
+ function normalizeDocUpdatedBy(value) {
7081
+ const trimmed = value?.trim() ?? "";
7082
+ if (!trimmed)
7083
+ return "";
7084
+ if (trimmed.toLowerCase() === "agentplane")
7085
+ return "";
7086
+ return trimmed;
7087
+ }
7088
+ function resolveDocUpdatedBy(task, author) {
7089
+ const fromAuthor = normalizeDocUpdatedBy(author);
7090
+ if (fromAuthor)
7091
+ return fromAuthor;
7092
+ const fromTask = normalizeDocUpdatedBy(typeof task.doc_updated_by === "string" ? task.doc_updated_by : undefined);
7093
+ if (fromTask)
7094
+ return fromTask;
7095
+ return normalizeDocUpdatedBy(typeof task.owner === "string" ? task.owner : undefined);
7096
+ }
7074
7097
  function splitCombinedHeadingLines(doc) {
7075
7098
  const lines = doc.replaceAll("\r\n", "\n").split("\n");
7076
7099
  const out = [];
@@ -1 +1 @@
1
- {"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../src/task-backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../src/task-backend.ts"],"names":[],"mappings":"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"}
@@ -42,13 +42,158 @@ function normalizeDoc(text) {
42
42
  .join("\n")
43
43
  .trim();
44
44
  }
45
+ function normalizeDocSectionName(section) {
46
+ return section.trim().replaceAll(/\s+/g, " ").toLowerCase();
47
+ }
48
+ function normalizeSectionLines(lines) {
49
+ const trimmedLines = [...lines];
50
+ while (trimmedLines.length > 0 && trimmedLines[0]?.trim() === "")
51
+ trimmedLines.shift();
52
+ while (trimmedLines.length > 0 && trimmedLines.at(-1)?.trim() === "")
53
+ trimmedLines.pop();
54
+ const out = [];
55
+ let inFence = false;
56
+ let pendingBlank = false;
57
+ for (const line of trimmedLines) {
58
+ const fenceCheck = line.trimStart();
59
+ if (fenceCheck.startsWith("```")) {
60
+ if (pendingBlank) {
61
+ out.push("");
62
+ pendingBlank = false;
63
+ }
64
+ out.push(line);
65
+ inFence = !inFence;
66
+ continue;
67
+ }
68
+ if (inFence) {
69
+ out.push(line);
70
+ continue;
71
+ }
72
+ if (line.trim() === "") {
73
+ pendingBlank = true;
74
+ continue;
75
+ }
76
+ if (pendingBlank) {
77
+ out.push("");
78
+ pendingBlank = false;
79
+ }
80
+ out.push(line);
81
+ }
82
+ return out;
83
+ }
84
+ function splitCombinedHeadingLines(doc) {
85
+ const lines = doc.replaceAll("\r\n", "\n").split("\n");
86
+ const out = [];
87
+ let inFence = false;
88
+ for (const line of lines) {
89
+ const trimmed = line.trimStart();
90
+ if (trimmed.startsWith("```")) {
91
+ inFence = !inFence;
92
+ out.push(line);
93
+ continue;
94
+ }
95
+ if (!inFence && line.includes("## ")) {
96
+ const matches = [...line.matchAll(/##\s+/g)];
97
+ if (matches.length > 1 && matches[0]?.index === 0) {
98
+ let start = 0;
99
+ for (let i = 1; i < matches.length; i += 1) {
100
+ const idx = matches[i]?.index ?? 0;
101
+ const chunk = line.slice(start, idx).trimEnd();
102
+ if (chunk)
103
+ out.push(chunk);
104
+ start = idx;
105
+ }
106
+ const last = line.slice(start).trimEnd();
107
+ if (last)
108
+ out.push(last);
109
+ continue;
110
+ }
111
+ }
112
+ out.push(line);
113
+ }
114
+ return out;
115
+ }
116
+ function normalizeTaskDoc(doc) {
117
+ const normalized = doc.replaceAll("\r\n", "\n");
118
+ const trimmed = normalized.replaceAll(/^\n+|\n+$/g, "");
119
+ if (!trimmed)
120
+ return "";
121
+ const lines = splitCombinedHeadingLines(trimmed);
122
+ const sections = new Map();
123
+ const order = [];
124
+ const pendingSeparator = new Set();
125
+ let currentKey = null;
126
+ for (const line of lines) {
127
+ const match = /^##\s+(.*)$/.exec(line.trim());
128
+ if (match) {
129
+ const title = match[1]?.trim() ?? "";
130
+ const key = normalizeDocSectionName(title);
131
+ if (key) {
132
+ const existing = sections.get(key);
133
+ if (existing) {
134
+ if (existing.lines.some((entry) => entry.trim() !== "")) {
135
+ pendingSeparator.add(key);
136
+ }
137
+ }
138
+ else {
139
+ sections.set(key, { title, lines: [] });
140
+ order.push(key);
141
+ }
142
+ currentKey = key;
143
+ continue;
144
+ }
145
+ }
146
+ if (currentKey) {
147
+ const entry = sections.get(currentKey);
148
+ if (!entry)
149
+ continue;
150
+ if (pendingSeparator.has(currentKey) && line.trim() !== "") {
151
+ entry.lines.push("");
152
+ pendingSeparator.delete(currentKey);
153
+ }
154
+ entry.lines.push(line);
155
+ }
156
+ }
157
+ if (order.length === 0)
158
+ return trimmed;
159
+ const out = [];
160
+ for (const key of order) {
161
+ const section = sections.get(key);
162
+ if (!section)
163
+ continue;
164
+ const normalizedLines = normalizeSectionLines(section.lines);
165
+ if (normalizedLines.length > 0) {
166
+ out.push(`## ${section.title}`, "", ...normalizedLines, "");
167
+ }
168
+ else {
169
+ out.push(`## ${section.title}`, "", "");
170
+ }
171
+ }
172
+ return out.join("\n").trimEnd();
173
+ }
45
174
  function docChanged(existing, updated) {
46
175
  return normalizeDoc(existing) !== normalizeDoc(updated);
47
176
  }
177
+ function normalizeUpdatedBy(value) {
178
+ if (typeof value !== "string")
179
+ return "";
180
+ const trimmed = value.trim();
181
+ if (!trimmed)
182
+ return "";
183
+ if (trimmed.toLowerCase() === DEFAULT_DOC_UPDATED_BY.toLowerCase())
184
+ return "";
185
+ return trimmed;
186
+ }
48
187
  function ensureDocMetadata(task, updatedBy) {
49
188
  task.doc_version = DOC_VERSION;
50
189
  task.doc_updated_at = nowIso();
51
- task.doc_updated_by = updatedBy ?? DEFAULT_DOC_UPDATED_BY;
190
+ const explicit = normalizeUpdatedBy(updatedBy);
191
+ if (updatedBy !== undefined) {
192
+ task.doc_updated_by =
193
+ explicit || resolveDocUpdatedByFromTask(task, DEFAULT_DOC_UPDATED_BY);
194
+ return;
195
+ }
196
+ task.doc_updated_by = resolveDocUpdatedByFromTask(task, DEFAULT_DOC_UPDATED_BY);
52
197
  }
53
198
  function lastCommentAuthor(comments) {
54
199
  if (!Array.isArray(comments))
@@ -69,31 +214,34 @@ function lastCommentAuthor(comments) {
69
214
  }
70
215
  function resolveDocUpdatedByFromFrontmatter(frontmatter, updatedBy, fallback) {
71
216
  if (updatedBy !== undefined) {
72
- const trimmed = updatedBy.trim();
73
- return trimmed.length > 0 ? trimmed : fallback;
217
+ const explicit = normalizeUpdatedBy(updatedBy);
218
+ if (explicit)
219
+ return explicit;
74
220
  }
75
221
  const author = lastCommentAuthor(frontmatter.comments);
76
222
  if (author)
77
223
  return author;
78
- const existing = frontmatter.doc_updated_by;
79
- if (typeof existing === "string") {
80
- const trimmed = existing.trim();
81
- if (trimmed)
82
- return trimmed;
83
- }
84
- return fallback;
224
+ const existing = normalizeUpdatedBy(frontmatter.doc_updated_by);
225
+ if (existing)
226
+ return existing;
227
+ const owner = normalizeUpdatedBy(frontmatter.owner);
228
+ if (owner)
229
+ return owner;
230
+ const fallbackValue = normalizeUpdatedBy(fallback);
231
+ return fallbackValue || fallback;
85
232
  }
86
233
  function resolveDocUpdatedByFromTask(task, fallback) {
87
234
  const author = lastCommentAuthor(task.comments);
88
235
  if (author)
89
236
  return author;
90
- const existing = task.doc_updated_by;
91
- if (typeof existing === "string") {
92
- const trimmed = existing.trim();
93
- if (trimmed)
94
- return trimmed;
95
- }
96
- return fallback;
237
+ const existing = normalizeUpdatedBy(task.doc_updated_by);
238
+ if (existing)
239
+ return existing;
240
+ const owner = normalizeUpdatedBy(task.owner);
241
+ if (owner)
242
+ return owner;
243
+ const fallbackValue = normalizeUpdatedBy(fallback);
244
+ return fallbackValue || fallback;
97
245
  }
98
246
  function isDocSectionHeader(line) {
99
247
  return DOC_SECTION_HEADER_RE.test(line.trim());
@@ -121,10 +269,11 @@ export function extractTaskDoc(body) {
121
269
  break;
122
270
  }
123
271
  }
124
- return lines.slice(startIdx, endIdx).join("\n").trimEnd();
272
+ const doc = lines.slice(startIdx, endIdx).join("\n").trimEnd();
273
+ return normalizeTaskDoc(doc);
125
274
  }
126
275
  export function mergeTaskDoc(body, doc) {
127
- const docText = String(doc ?? "").replaceAll(/^\n+|\n+$/g, "");
276
+ const docText = normalizeTaskDoc(String(doc ?? ""));
128
277
  if (docText) {
129
278
  const lines = body ? body.split("\n") : [];
130
279
  let prefixIdx = null;
@@ -263,7 +412,7 @@ function taskDataToExport(task) {
263
412
  : [],
264
413
  doc_version: task.doc_version ?? DOC_VERSION,
265
414
  doc_updated_at: task.doc_updated_at ?? "",
266
- doc_updated_by: task.doc_updated_by ?? DEFAULT_DOC_UPDATED_BY,
415
+ doc_updated_by: resolveDocUpdatedByFromTask(task, DEFAULT_DOC_UPDATED_BY),
267
416
  dirty: Boolean(task.dirty),
268
417
  id_source: task.id_source ?? "generated",
269
418
  };
@@ -445,7 +594,7 @@ export class LocalBackend {
445
594
  payload.doc_updated_at = nowIso();
446
595
  }
447
596
  if (payload.doc_updated_by === undefined || payload.doc_updated_by === "") {
448
- payload.doc_updated_by = this.updatedBy;
597
+ payload.doc_updated_by = resolveDocUpdatedByFromTask(task, this.updatedBy);
449
598
  }
450
599
  await mkdir(path.dirname(readme), { recursive: true });
451
600
  const text = renderTaskReadme(payload, body || "");
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export function getVersion() {
2
- return "0.1.3";
2
+ return "0.1.4";
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentplane",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Agent Plane CLI for task workflows, recipes, and project automation.",
5
5
  "keywords": [
6
6
  "agentplane",
@@ -54,6 +54,6 @@
54
54
  "prepublishOnly": "npm run prepack"
55
55
  },
56
56
  "dependencies": {
57
- "@agentplaneorg/core": "0.1.3"
57
+ "@agentplaneorg/core": "0.1.4"
58
58
  }
59
59
  }