monoco-toolkit 0.3.5__py3-none-any.whl → 0.3.6__py3-none-any.whl

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.
@@ -221,6 +221,10 @@ def create_issue_file(
221
221
  if not find_issue_path(issues_root, rel_id):
222
222
  raise ValueError(f"Related issue {rel_id} not found.")
223
223
 
224
+ # Auto-assign default parent for non-epic types if not provided
225
+ if issue_type != IssueType.EPIC and not parent:
226
+ parent = "EPIC-0000"
227
+
224
228
  issue_id = find_next_id(issue_type, issues_root)
225
229
  base_type_dir = get_issue_dir(issue_type, issues_root)
226
230
  target_dir = base_type_dir / status
@@ -169,35 +169,6 @@ class StateMachine:
169
169
  if meta.stage is None:
170
170
  meta.stage = "draft"
171
171
 
172
- def validate_transition(
173
- self,
174
- from_status: str,
175
- from_stage: Optional[str],
176
- to_status: str,
177
- to_stage: Optional[str],
178
- solution: Optional[str] = None,
179
- ) -> None:
180
- """
181
- Validate if a transition is allowed. Raises ValueError if not.
182
- """
183
- if from_status == to_status and from_stage == to_stage:
184
- return # No change is always allowed (unless we want to enforce specific updates)
185
-
186
- transition = self.find_transition(
187
- from_status, from_stage, to_status, to_stage, solution
188
- )
189
-
190
- if not transition:
191
- raise ValueError(
192
- f"Lifecycle Policy: Transition from {from_status}({from_stage if from_stage else 'None'}) "
193
- f"to {to_status}({to_stage if to_stage else 'None'}) is not defined."
194
- )
195
-
196
- if transition.required_solution and solution != transition.required_solution:
197
- raise ValueError(
198
- f"Lifecycle Policy: Transition '{transition.label}' requires solution '{transition.required_solution}'."
199
- )
200
-
201
172
  def enforce_policy(self, meta: IssueMetadata) -> None:
202
173
  """
203
174
  Apply consistency rules to IssueMetadata.
@@ -1,6 +1,6 @@
1
1
  from enum import Enum
2
2
  from typing import List, Optional, Any, Dict
3
- from pydantic import BaseModel, Field, model_validator
3
+ from pydantic import BaseModel, Field, model_validator, ConfigDict
4
4
  from datetime import datetime
5
5
  import hashlib
6
6
  import secrets
@@ -105,13 +105,13 @@ class IssueAction(BaseModel):
105
105
 
106
106
 
107
107
  class IssueMetadata(BaseModel):
108
- model_config = {"extra": "allow"}
108
+ model_config = ConfigDict(extra="allow", validate_assignment=True)
109
109
 
110
110
  id: str
111
111
  uid: Optional[str] = None # Global unique identifier for cross-project identity
112
- type: str
113
- status: str = "open"
114
- stage: Optional[str] = None
112
+ type: IssueType
113
+ status: IssueStatus = IssueStatus.OPEN
114
+ stage: Optional[IssueStage] = None
115
115
  title: str
116
116
 
117
117
  # Time Anchors
@@ -122,7 +122,7 @@ class IssueMetadata(BaseModel):
122
122
 
123
123
  parent: Optional[str] = None
124
124
  sprint: Optional[str] = None
125
- solution: Optional[str] = None
125
+ solution: Optional[IssueSolution] = None
126
126
  isolation: Optional[IssueIsolation] = None
127
127
  dependencies: List[str] = []
128
128
  related: List[str] = []
@@ -161,26 +161,56 @@ class IssueMetadata(BaseModel):
161
161
  # Normalize type and status to lowercase for compatibility
162
162
  if "type" in v and isinstance(v["type"], str):
163
163
  v["type"] = v["type"].lower()
164
+ try:
165
+ v["type"] = IssueType(v["type"])
166
+ except ValueError:
167
+ pass
168
+
164
169
  if "status" in v and isinstance(v["status"], str):
165
170
  v["status"] = v["status"].lower()
171
+ try:
172
+ v["status"] = IssueStatus(v["status"])
173
+ except ValueError:
174
+ pass
175
+
166
176
  if "solution" in v and isinstance(v["solution"], str):
167
177
  v["solution"] = v["solution"].lower()
178
+ try:
179
+ v["solution"] = IssueSolution(v["solution"])
180
+ except ValueError:
181
+ pass
182
+
168
183
  # Stage normalization
169
184
  if "stage" in v and isinstance(v["stage"], str):
170
185
  v["stage"] = v["stage"].lower()
171
186
  if v["stage"] == "todo":
172
187
  v["stage"] = "draft"
188
+ try:
189
+ v["stage"] = IssueStage(v["stage"])
190
+ except ValueError:
191
+ pass
173
192
  return v
174
193
 
175
194
  @model_validator(mode="after")
176
195
  def validate_lifecycle(self) -> "IssueMetadata":
177
- # Logic Definition:
178
- # status: backlog -> stage: freezed
179
- # status: closed -> stage: done
180
- # status: open -> stage: draft | doing | review | done (default draft)
181
-
182
- # NOTE: We do NOT auto-correct state here anymore to allow Linter to detect inconsistencies.
183
- # Auto-correction should be applied explicitly by 'create' or 'update' commands via core logic.
196
+ # 1. Solution Consistency: Closed issues MUST have a solution
197
+ if self.status == IssueStatus.CLOSED and not self.solution:
198
+ raise ValueError(f"Issue '{self.id}' is closed but 'solution' is missing.")
199
+
200
+ # 2. Hierarchy Consistency: non-epic types MUST have a parent (except specific root seeds)
201
+ if self.type != IssueType.EPIC and not self.parent:
202
+ # We allow exceptions for very specific bootstrap cases if needed, but currently enforce it.
203
+ if self.id not in ["FEAT-BOOTSTRAP"]: # Example exception
204
+ raise ValueError(
205
+ f"Issue '{self.id}' of type '{self.type}' must have a 'parent' reference."
206
+ )
207
+
208
+ # 3. State/Stage Consistency (Warnings or Errors)
209
+ # Note: In Monoco, status: closed is tightly coupled with stage: done
210
+ if self.status == IssueStatus.CLOSED and self.stage != IssueStage.DONE:
211
+ # We could auto-fix here, but let's be strict for Validation purposes
212
+ # raise ValueError(f"Issue '{self.id}' is closed but stage is '{self.stage}' (expected 'done').")
213
+ pass
184
214
 
185
215
  return self
186
216
 
@@ -16,6 +16,7 @@ def test_validator_namespaced_reference_in_body():
16
16
  opened_at=datetime.now(),
17
17
  updated_at=datetime.now(),
18
18
  domains=["intelligence"],
19
+ parent="EPIC-0000",
19
20
  )
20
21
 
21
22
  # Context: toolkit project, monoco workspace
@@ -0,0 +1,3 @@
1
+ from .cli import app
2
+
3
+ __all__ = ["app"]
@@ -0,0 +1,90 @@
1
+ import typer
2
+ from pathlib import Path
3
+ from typing import Optional
4
+ from rich.console import Console
5
+ from rich.table import Table
6
+ from monoco.core.config import get_config
7
+ from .core import add_memo, list_memos, get_inbox_path
8
+
9
+ app = typer.Typer(help="Manage memos (fleeting notes).")
10
+ console = Console()
11
+
12
+
13
+ def get_issues_root() -> Path:
14
+ config = get_config()
15
+ # Resolve absolute path for issues
16
+ root = Path(config.paths.root).resolve()
17
+ # If config.paths.root is '.', it means current or discovered root.
18
+ # We should trust get_config's loading mechanism, but find_monoco_root might be safer to base off.
19
+ # Update: config is loaded relative to where it was found.
20
+ # Let's rely on config.paths.root if it's absolute, or relative to CWD?
21
+ # Actually, the ConfigLoader doesn't mutate paths.root based on location.
22
+ # It defaults to "."
23
+
24
+ # Better approach:
25
+ # Use find_monoco_root() to get base, then append config.paths.issues
26
+ from monoco.core.config import find_monoco_root
27
+
28
+ project_root = find_monoco_root()
29
+ return project_root / config.paths.issues
30
+
31
+
32
+ @app.command("add")
33
+ def add_command(
34
+ content: str = typer.Argument(..., help="The content of the memo."),
35
+ context: Optional[str] = typer.Option(
36
+ None, "--context", "-c", help="Context reference (e.g. file:line)."
37
+ ),
38
+ ):
39
+ """
40
+ Capture a new idea or thought into the Memo Inbox.
41
+ """
42
+ issues_root = get_issues_root()
43
+
44
+ uid = add_memo(issues_root, content, context)
45
+
46
+ console.print(f"[green]✔ Memo recorded.[/green] ID: [bold]{uid}[/bold]")
47
+
48
+
49
+ @app.command("list")
50
+ def list_command():
51
+ """
52
+ List all memos in the inbox.
53
+ """
54
+ issues_root = get_issues_root()
55
+
56
+ memos = list_memos(issues_root)
57
+
58
+ if not memos:
59
+ console.print("No memos found. Use `monoco memo add` to create one.")
60
+ return
61
+
62
+ table = Table(title="Memo Inbox")
63
+ table.add_column("ID", style="cyan", no_wrap=True)
64
+ table.add_column("Timestamp", style="magenta")
65
+ table.add_column("Content")
66
+
67
+ for memo in memos:
68
+ # Truncate content for list view
69
+ content_preview = memo["content"].split("\n")[0]
70
+ if len(memo["content"]) > 50:
71
+ content_preview = content_preview[:47] + "..."
72
+
73
+ table.add_row(memo["id"], memo["timestamp"], content_preview)
74
+
75
+ console.print(table)
76
+
77
+
78
+ @app.command("open")
79
+ def open_command():
80
+ """
81
+ Open the inbox file in the default editor.
82
+ """
83
+ issues_root = get_issues_root()
84
+ inbox_path = get_inbox_path(issues_root)
85
+
86
+ if not inbox_path.exists():
87
+ console.print("[yellow]Inbox does not exist yet.[/yellow]")
88
+ return
89
+
90
+ typer.launch(str(inbox_path))
@@ -0,0 +1,87 @@
1
+ import re
2
+ from pathlib import Path
3
+ from datetime import datetime
4
+ from typing import List, Dict, Optional
5
+ import secrets
6
+
7
+
8
+ def get_memos_dir(issues_root: Path) -> Path:
9
+ """
10
+ Get the directory for memos.
11
+ Convention: Sibling of Issues directory.
12
+ """
13
+ # issues_root is usually ".../Issues"
14
+ return issues_root.parent / "Memos"
15
+
16
+
17
+ def get_inbox_path(issues_root: Path) -> Path:
18
+ return get_memos_dir(issues_root) / "inbox.md"
19
+
20
+
21
+ def generate_memo_id() -> str:
22
+ """Generate a short 6-char ID."""
23
+ return secrets.token_hex(3)
24
+
25
+
26
+ def format_memo(uid: str, content: str, context: Optional[str] = None) -> str:
27
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
28
+ header = f"## [{uid}] {timestamp}"
29
+
30
+ body = content.strip()
31
+
32
+ if context:
33
+ body = f"> **Context**: `{context}`\n\n{body}"
34
+
35
+ return f"\n{header}\n{body}\n"
36
+
37
+
38
+ def add_memo(issues_root: Path, content: str, context: Optional[str] = None) -> str:
39
+ """
40
+ Append a memo to the inbox.
41
+ Returns the generated UID.
42
+ """
43
+ inbox_path = get_inbox_path(issues_root)
44
+
45
+ if not inbox_path.exists():
46
+ inbox_path.parent.mkdir(parents=True, exist_ok=True)
47
+ inbox_path.write_text("# Monoco Memos Inbox\n", encoding="utf-8")
48
+
49
+ uid = generate_memo_id()
50
+ entry = format_memo(uid, content, context)
51
+
52
+ with inbox_path.open("a", encoding="utf-8") as f:
53
+ f.write(entry)
54
+
55
+ return uid
56
+
57
+
58
+ def list_memos(issues_root: Path) -> List[Dict[str, str]]:
59
+ """
60
+ Parse memos from inbox.
61
+ """
62
+ inbox_path = get_inbox_path(issues_root)
63
+ if not inbox_path.exists():
64
+ return []
65
+
66
+ content = inbox_path.read_text(encoding="utf-8")
67
+
68
+ # Regex to find headers: ## [uid] timestamp
69
+ # We split by headers
70
+
71
+ pattern = re.compile(r"^## \[([a-f0-9]+)\] (.*?)$", re.MULTILINE)
72
+
73
+ memos = []
74
+ matches = list(pattern.finditer(content))
75
+
76
+ for i, match in enumerate(matches):
77
+ uid = match.group(1)
78
+ timestamp = match.group(2)
79
+
80
+ start = match.end()
81
+ end = matches[i + 1].start() if i + 1 < len(matches) else len(content)
82
+
83
+ body = content[start:end].strip()
84
+
85
+ memos.append({"id": uid, "timestamp": timestamp, "content": body})
86
+
87
+ return memos
@@ -1,6 +1,6 @@
1
1
  from datetime import datetime
2
2
  from typing import Optional
3
- from pydantic import BaseModel, Field
3
+ from pydantic import BaseModel, Field, ConfigDict
4
4
  from .worker import Worker
5
5
 
6
6
 
@@ -10,6 +10,8 @@ class Session(BaseModel):
10
10
  Persisted state of the session.
11
11
  """
12
12
 
13
+ model_config = ConfigDict(arbitrary_types_allowed=True)
14
+
13
15
  id: str = Field(..., description="Unique session ID (likely UUID)")
14
16
  issue_id: str = Field(..., description="The Issue ID this session is working on")
15
17
  role_name: str = Field(..., description="Name of the role employed")
@@ -24,9 +26,6 @@ class Session(BaseModel):
24
26
  # History could be a list of logs or pointers to git commits
25
27
  # For now, let's keep it simple. The git log IS the history.
26
28
 
27
- class Config:
28
- arbitrary_types_allowed = True
29
-
30
29
 
31
30
  class RuntimeSession:
32
31
  """
monoco/main.py CHANGED
@@ -171,6 +171,10 @@ from monoco.features.scheduler import cli as scheduler_cmd
171
171
  app.add_typer(scheduler_cmd.app, name="agent", help="Manage agent sessions")
172
172
  app.add_typer(scheduler_cmd.role_app, name="role", help="Manage agent roles")
173
173
 
174
+ from monoco.features.memo import app as memo_app
175
+
176
+ app.add_typer(memo_app, name="memo", help="Manage fleeting notes (memos)")
177
+
174
178
 
175
179
  from monoco.daemon.commands import serve
176
180
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: monoco-toolkit
3
- Version: 0.3.5
3
+ Version: 0.3.6
4
4
  Summary: Agent Native Toolkit for Monoco - Task Management & Kanban for AI Agents
5
5
  Project-URL: Homepage, https://monoco.io
6
6
  Project-URL: Repository, https://github.com/IndenScale/Monoco
@@ -1,4 +1,4 @@
1
- monoco/main.py,sha256=MscjwDCOT2DfZKpZMEZEn-M1INmqu4-4R200GEiBwrc,5562
1
+ monoco/main.py,sha256=IF8pN71fFL0AwxtnRxXQaoi9NgBf0YAhppWlc8SuiTM,5688
2
2
  monoco/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  monoco/cli/project.py,sha256=FqLaDD3hiWxa0_TKzxEF7PYH9RPsvmLyjO3NYVckgGs,2737
4
4
  monoco/cli/workspace.py,sha256=1TVVS835XyirLDvBGQXSblIaYVhe2Pk9EpORDvcktyk,1538
@@ -42,15 +42,15 @@ monoco/features/i18n/resources/zh/AGENTS.md,sha256=lKkwLLCADRH7UDq9no4eQY2sRfJrb
42
42
  monoco/features/i18n/resources/zh/SKILL.md,sha256=Wynk7zVBW7CO0_6AEQNUvlD_3eMW_7EPnzEn9QUaiDs,1884
43
43
  monoco/features/issue/adapter.py,sha256=4dzKg4-0XH63uORoh8qcolvKxJR6McBDIYxYEcZJJkA,1204
44
44
  monoco/features/issue/commands.py,sha256=vaScb2J4qjUvO8DSlKhTrGDSfIyJ4zIUr14jhBlG6tE,37581
45
- monoco/features/issue/core.py,sha256=kRyUbYqEBno0Zoogq7dMIcQv5M0QIRSlptvzp0pfImE,51302
45
+ monoco/features/issue/core.py,sha256=9b5BVJJz5Ek3QNKqOhn6GSgvkmpAN45zmb8CQJVsPjc,51452
46
46
  monoco/features/issue/domain_commands.py,sha256=eatSF_uZp4nGpVr2PIgb00MWfEBm0OnyAd4JvUJEAAA,1535
47
47
  monoco/features/issue/domain_service.py,sha256=bEs_WXOWmotgIR-lGwyWekF4nonvjsgrK1YG3pyVfwk,2564
48
48
  monoco/features/issue/linter.py,sha256=LLtJEVIzoGTNm1liZARJHM3-V-EODkGRuw3ExCZtEjY,26115
49
49
  monoco/features/issue/migration.py,sha256=i0xlxZjrpmuHGHOAIN4iu31EwwVIvZn7yjveS-kU22c,4896
50
- monoco/features/issue/models.py,sha256=7oIMxvUEfe00n7wni9bZgKU2e9404flvArixbLQ95Dg,5902
50
+ monoco/features/issue/models.py,sha256=pIgun9dDTelDJa6RqhLJb2OR201cimOoNEB78qUsvG0,7286
51
51
  monoco/features/issue/monitor.py,sha256=vZN0TbR3V5fHKHRGkIhimO6UwWcwYjDHQs2qzjEG174,3549
52
52
  monoco/features/issue/resolver.py,sha256=mAU9s7TNNHY9A2278JTwJvxU-jalGKTDJfJdjONev3E,5655
53
- monoco/features/issue/test_priority_integration.py,sha256=Kq3XMQYkQK62R-a_lmAeEpGlZr4nRBbG6WAyW430el8,2763
53
+ monoco/features/issue/test_priority_integration.py,sha256=pTBg3Wjv6lLYxWL6vjbo2NGVE-X0MRB3Ha8bqObZrU4,2791
54
54
  monoco/features/issue/test_resolver.py,sha256=luFhK37DUvh4a3TTcFYVO-oOIJljQVCSYicwSWyDleQ,2530
55
55
  monoco/features/issue/validator.py,sha256=GYqbx2-ZxXfk1HicgBXkpL__v83KK-jcOyo7eW-VRUs,27793
56
56
  monoco/features/issue/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -60,7 +60,7 @@ monoco/features/issue/domain/parser.py,sha256=axfB9BjY-m4DQqYwTQBm_38plOidZaDqFt
60
60
  monoco/features/issue/domain/workspace.py,sha256=nyTEFNmpLPuX7nssMCBiFI1XBhY9zbqG877Ppp_s0Fg,3658
61
61
  monoco/features/issue/engine/__init__.py,sha256=-SBvzjlZJz0O-IB1c95d9pbhr3lydJNLq2vhnfkZ8PQ,747
62
62
  monoco/features/issue/engine/config.py,sha256=7enjPW4J_fpuK08ov6LpfQ-9h2T1D4Hc5yIXOPuQvLs,5761
63
- monoco/features/issue/engine/machine.py,sha256=Bun_5jHlFRA7Duy7zG8f1GZIbZlPKt6C7RZ4vP7qJWc,7503
63
+ monoco/features/issue/engine/machine.py,sha256=BTYjp8NQAzu8JVP95bQdkOLrJjFsRNR7uC8tjsUTqCk,6393
64
64
  monoco/features/issue/engine/models.py,sha256=595Sx3ncrpg_PhnbBLthohAvuhnjA-_9oXcrsT6Lv0k,574
65
65
  monoco/features/issue/lsp/__init__.py,sha256=8bl8-WzSj3C4SkPKgVGnCeyemmvHVWBsuMZsJuJggG8,77
66
66
  monoco/features/issue/lsp/definition.py,sha256=cF6Quw1OztuKMJ1zLvgA_ek7lTAdzHF0m4LVznpbAPw,3203
@@ -68,6 +68,9 @@ monoco/features/issue/resources/en/AGENTS.md,sha256=eHHXjLRDAV7IKrYPQSilxu0X5D0S
68
68
  monoco/features/issue/resources/en/SKILL.md,sha256=M5khTJdraQenX0tf7RHOVcqyKHC285qwDzWdsCJ7XPI,4032
69
69
  monoco/features/issue/resources/zh/AGENTS.md,sha256=oRHHqeDYx6aEc5FfdL7a-zqT7uh4SYIYt8QBRKEKrYM,1351
70
70
  monoco/features/issue/resources/zh/SKILL.md,sha256=XFE33cCCos0U1IVNkMhU7fGuqVqfxo_FNKdp1aScaoM,5055
71
+ monoco/features/memo/__init__.py,sha256=ledMrs-h5k_4wssXWv4MBYTDi-HHo3Fv8QAMpqlQI_M,40
72
+ monoco/features/memo/cli.py,sha256=nw5Kg7Qu33ucwrBaJS5CIkPRA_6TlJQQz2TvDWL2Nqc,2685
73
+ monoco/features/memo/core.py,sha256=HUQLohVZ6KCU2chi18tEQYtohzl1-bOR5F12W40QkIc,2226
71
74
  monoco/features/scheduler/__init__.py,sha256=hvE9A14qFTeTYbWlK9iMRdXIFLMBuG8724GEZzFTHB8,483
72
75
  monoco/features/scheduler/cli.py,sha256=NgsGwCf615YA4VGd-mqMpGp5VCjdMUqoZqiHZFnDdLU,8325
73
76
  monoco/features/scheduler/config.py,sha256=69PTvKGHJ33fA2yhFJAq0WVq70Zbmdd5X8Wl0vIYAak,2336
@@ -76,7 +79,7 @@ monoco/features/scheduler/engines.py,sha256=ICKw4Kfme6UNl_JLJvT7hADKHo76Yr8wpFFE
76
79
  monoco/features/scheduler/manager.py,sha256=PmNKqfktgrdpUwE-jPE_WX3IvzZat0JKdEcmzse08-0,1680
77
80
  monoco/features/scheduler/models.py,sha256=rb8rx8t_TD5ilUC6xU3jvK0sud7YUZE_iEdes9Np8R0,877
78
81
  monoco/features/scheduler/reliability.py,sha256=zVwtnksug5wr0_tigC2Qjl_C8VNyrheN_34ItUceGoo,3846
79
- monoco/features/scheduler/session.py,sha256=V1xFXA65BaERhBwRYIecaye2TjDtFvAzuIy2gZ68ag8,2954
82
+ monoco/features/scheduler/session.py,sha256=5xga191nWXqJOLgl3MTTJ3zDrVZcj8SxZcxYM6-CtLU,2969
80
83
  monoco/features/scheduler/worker.py,sha256=4OU2Y7nG5EKadNIKDF5GWl5V7vgVl3OPlYHShfiEeBI,4538
81
84
  monoco/features/skills/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
85
  monoco/features/skills/core.py,sha256=BXVvMot8E457-pj9U19lPHypBVhdLQRsx0zEAXJxpGY,3436
@@ -87,8 +90,8 @@ monoco/features/spike/resources/en/AGENTS.md,sha256=NG3CMnlDk_0J8hnRUcueAM9lgIQr
87
90
  monoco/features/spike/resources/en/SKILL.md,sha256=qKDcVh0D3pDRvfNLh1Bzo4oQU3obpl4tqdlzxeiWYMk,1911
88
91
  monoco/features/spike/resources/zh/AGENTS.md,sha256=5RHNl7fc3RdYYTFH483ojJl_arGPKkyYziOuGgFbqqg,290
89
92
  monoco/features/spike/resources/zh/SKILL.md,sha256=Q82e9lCQOAYIwBs5rGnvlVUDq7bp0pz8yvO10KTWFYQ,1710
90
- monoco_toolkit-0.3.5.dist-info/METADATA,sha256=UD0y77LYaDLy3ZoMUphV87XScSEg8G3kGxld1DhD8Wk,4732
91
- monoco_toolkit-0.3.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
92
- monoco_toolkit-0.3.5.dist-info/entry_points.txt,sha256=iYj7FWYBdtClU15-Du1skqD0s6SFSIhJvxJ29VWp8ng,43
93
- monoco_toolkit-0.3.5.dist-info/licenses/LICENSE,sha256=ACAGGjV6aod4eIlVUTx1q9PZbnZGN5bBwkSs9RHj83s,1071
94
- monoco_toolkit-0.3.5.dist-info/RECORD,,
93
+ monoco_toolkit-0.3.6.dist-info/METADATA,sha256=UZH_Na2LgWBEQ8KWU084wgO8l9AK_HlTRc2YD58DT8o,4732
94
+ monoco_toolkit-0.3.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
95
+ monoco_toolkit-0.3.6.dist-info/entry_points.txt,sha256=iYj7FWYBdtClU15-Du1skqD0s6SFSIhJvxJ29VWp8ng,43
96
+ monoco_toolkit-0.3.6.dist-info/licenses/LICENSE,sha256=ACAGGjV6aod4eIlVUTx1q9PZbnZGN5bBwkSs9RHj83s,1071
97
+ monoco_toolkit-0.3.6.dist-info/RECORD,,