lattice-cli 0.1.2__tar.gz → 0.2.0__tar.gz
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.
- {lattice_cli-0.1.2/src/lattice_cli.egg-info → lattice_cli-0.2.0}/PKG-INFO +3 -2
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/README.md +2 -1
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/pyproject.toml +1 -1
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/__init__.py +1 -1
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/cli.py +1 -1
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/formatters.py +70 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0/src/lattice_cli.egg-info}/PKG-INFO +3 -2
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice_cli.egg-info/SOURCES.txt +2 -1
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_cli.py +1 -1
- lattice_cli-0.2.0/tests/test_yaml_format.py +130 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/LICENSE +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/setup.cfg +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/__main__.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/agent.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/constraints.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/ipog.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/model.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/parser.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/claude/lattice-workflow/SKILL.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/claude/lattice-workflow/references/modeling-rules.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/claude/lattice-workflow/references/worked-examples.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/codex/lattice-workflow/SKILL.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/codex/lattice-workflow/agents/openai.yaml +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/codex/lattice-workflow/references/modeling-rules.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/codex/lattice-workflow/references/worked-examples.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/generic/lattice-workflow/SKILL.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/generic/lattice-workflow/references/modeling-rules.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/generic/lattice-workflow/references/worked-examples.md +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice_cli.egg-info/dependency_links.txt +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice_cli.egg-info/entry_points.txt +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice_cli.egg-info/requires.txt +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice_cli.egg-info/top_level.txt +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_agent_bootstrap_matrix.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_constraints.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_examples.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_ipog.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_model.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_parser.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_schema_guidance_matrix.py +0 -0
- {lattice_cli-0.1.2 → lattice_cli-0.2.0}/tests/test_self_hosting_matrix.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lattice-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Deterministic combinatorial coverage for agent workflows and constrained variant surfaces.
|
|
5
5
|
Author-email: Tyler Klose <tylerklose@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -105,11 +105,12 @@ Supported output formats:
|
|
|
105
105
|
- `table`
|
|
106
106
|
- `csv`
|
|
107
107
|
- `summary`
|
|
108
|
+
- `yaml` (same content as `json`, for files people edit by hand)
|
|
108
109
|
|
|
109
110
|
`generate` defaults to JSON because the primary consumer is usually a coding harness. File-based schemas are supported, but the schema file is transport, not the product surface.
|
|
110
111
|
|
|
111
112
|
For long higher-strength runs, use `--progress` to stream coverage progress to
|
|
112
|
-
stderr while keeping stdout clean for JSON, CSV, table, or summary output.
|
|
113
|
+
stderr while keeping stdout clean for JSON, YAML, CSV, table, or summary output.
|
|
113
114
|
`--progress-every N` controls how many generated scenarios pass between
|
|
114
115
|
updates.
|
|
115
116
|
|
|
@@ -77,11 +77,12 @@ Supported output formats:
|
|
|
77
77
|
- `table`
|
|
78
78
|
- `csv`
|
|
79
79
|
- `summary`
|
|
80
|
+
- `yaml` (same content as `json`, for files people edit by hand)
|
|
80
81
|
|
|
81
82
|
`generate` defaults to JSON because the primary consumer is usually a coding harness. File-based schemas are supported, but the schema file is transport, not the product surface.
|
|
82
83
|
|
|
83
84
|
For long higher-strength runs, use `--progress` to stream coverage progress to
|
|
84
|
-
stderr while keeping stdout clean for JSON, CSV, table, or summary output.
|
|
85
|
+
stderr while keeping stdout clean for JSON, YAML, CSV, table, or summary output.
|
|
85
86
|
`--progress-every N` controls how many generated scenarios pass between
|
|
86
87
|
updates.
|
|
87
88
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lattice-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "Deterministic combinatorial coverage for agent workflows and constrained variant surfaces."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -92,7 +92,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
92
92
|
)
|
|
93
93
|
generate.add_argument("model", nargs="?", help="Path to a JSON or YAML schema. Reads stdin when omitted.")
|
|
94
94
|
generate.add_argument("--strength", type=int, help="Override the schema strength.")
|
|
95
|
-
generate.add_argument("--format", default="json", choices=("table", "json", "csv", "summary"))
|
|
95
|
+
generate.add_argument("--format", default="json", choices=("table", "json", "csv", "summary", "yaml"))
|
|
96
96
|
generate.add_argument("--seed", type=int, default=42)
|
|
97
97
|
generate.add_argument("--pool-size", type=int, default=50)
|
|
98
98
|
generate.add_argument(
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import csv
|
|
4
4
|
import io
|
|
5
5
|
import json
|
|
6
|
+
import re
|
|
6
7
|
|
|
7
8
|
from lattice.ipog import GenerationResult
|
|
8
9
|
from lattice.model import Model
|
|
@@ -17,6 +18,8 @@ def render_output(model: Model, result: GenerationResult, *, output_format: str,
|
|
|
17
18
|
return format_csv(model, result)
|
|
18
19
|
if output_format == "summary":
|
|
19
20
|
return format_summary(model, result)
|
|
21
|
+
if output_format == "yaml":
|
|
22
|
+
return format_yaml(model, result, seed=seed)
|
|
20
23
|
raise ValueError(f"Unknown format `{output_format}`.")
|
|
21
24
|
|
|
22
25
|
|
|
@@ -85,6 +88,73 @@ def format_json(model: Model, result: GenerationResult, *, seed: int) -> str:
|
|
|
85
88
|
return json.dumps(payload, indent=2)
|
|
86
89
|
|
|
87
90
|
|
|
91
|
+
def format_yaml(model: Model, result: GenerationResult, *, seed: int | None) -> str:
|
|
92
|
+
"""Same content as format_json, written by hand in one fixed style.
|
|
93
|
+
|
|
94
|
+
PyYAML and Ruby's Psych quote and wrap differently, so the Python and Ruby
|
|
95
|
+
implementations write YAML themselves to emit identical bytes. Every string
|
|
96
|
+
is double-quoted, so no value can be read back as a boolean, null, number
|
|
97
|
+
or date.
|
|
98
|
+
"""
|
|
99
|
+
coverage = f"{result.coverage_curve[-1].cumulative_pct:.1f}%" if result.coverage_curve else "0.0%"
|
|
100
|
+
lines = [
|
|
101
|
+
"meta:",
|
|
102
|
+
f" model_name: {_yaml_string(model.model_name)}",
|
|
103
|
+
f" strength: {model.strength}",
|
|
104
|
+
f" test_count: {len(result.rows)}",
|
|
105
|
+
f" exhaustive_count: {model.exhaustive_count}",
|
|
106
|
+
f" reduction: {_yaml_string(_reduction_label(model.exhaustive_count, len(result.rows)))}",
|
|
107
|
+
f" coverage: {_yaml_string(coverage)}",
|
|
108
|
+
f" seed: {'null' if seed is None else seed}",
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
if not result.coverage_curve:
|
|
112
|
+
lines.append("coverage_curve: []")
|
|
113
|
+
else:
|
|
114
|
+
lines.append("coverage_curve:")
|
|
115
|
+
for point in result.coverage_curve:
|
|
116
|
+
lines.append(f" - scenario: {point.scenario}")
|
|
117
|
+
lines.append(f" cumulative_pct: {json.dumps(point.cumulative_pct)}")
|
|
118
|
+
|
|
119
|
+
rows = _named_rows(model, result)
|
|
120
|
+
if not rows:
|
|
121
|
+
lines.append("scenarios: []")
|
|
122
|
+
else:
|
|
123
|
+
lines.append("scenarios:")
|
|
124
|
+
for index, row in enumerate(rows):
|
|
125
|
+
lines.append(f" - id: {index + 1}")
|
|
126
|
+
lines.append(" values:")
|
|
127
|
+
for name in model.parameter_names:
|
|
128
|
+
lines.append(f" {_yaml_string(name)}: {_yaml_string(row[name])}")
|
|
129
|
+
return "\n".join(lines)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
_YAML_ESCAPES = {
|
|
133
|
+
'"': '\\"',
|
|
134
|
+
"\\": "\\\\",
|
|
135
|
+
"\b": "\\b",
|
|
136
|
+
"\t": "\\t",
|
|
137
|
+
"\n": "\\n",
|
|
138
|
+
"\f": "\\f",
|
|
139
|
+
"\r": "\\r",
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
# Characters escaped inside a double-quoted YAML string: the quote and
|
|
143
|
+
# backslash, C0 controls, DEL, C1 controls (U+0085 would otherwise fold to a
|
|
144
|
+
# space), the Unicode line and paragraph separators, the byte-order mark, and
|
|
145
|
+
# the two noncharacters YAML cannot hold. Everything else is written as UTF-8,
|
|
146
|
+
# so accented letters and emoji stay readable.
|
|
147
|
+
_YAML_ESCAPED_CHARS = re.compile(r'["\\\u0000-\u001f\u007f-\u009f\u2028\u2029\ufeff\ufffe\uffff]')
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _yaml_string(value: str) -> str:
|
|
151
|
+
def escape(match: re.Match[str]) -> str:
|
|
152
|
+
char = match.group(0)
|
|
153
|
+
return _YAML_ESCAPES.get(char) or f"\\u{ord(char):04x}"
|
|
154
|
+
|
|
155
|
+
return '"' + _YAML_ESCAPED_CHARS.sub(escape, value) + '"'
|
|
156
|
+
|
|
157
|
+
|
|
88
158
|
def format_csv(model: Model, result: GenerationResult) -> str:
|
|
89
159
|
buffer = io.StringIO()
|
|
90
160
|
writer = csv.writer(buffer)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lattice-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Deterministic combinatorial coverage for agent workflows and constrained variant surfaces.
|
|
5
5
|
Author-email: Tyler Klose <tylerklose@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -105,11 +105,12 @@ Supported output formats:
|
|
|
105
105
|
- `table`
|
|
106
106
|
- `csv`
|
|
107
107
|
- `summary`
|
|
108
|
+
- `yaml` (same content as `json`, for files people edit by hand)
|
|
108
109
|
|
|
109
110
|
`generate` defaults to JSON because the primary consumer is usually a coding harness. File-based schemas are supported, but the schema file is transport, not the product surface.
|
|
110
111
|
|
|
111
112
|
For long higher-strength runs, use `--progress` to stream coverage progress to
|
|
112
|
-
stderr while keeping stdout clean for JSON, CSV, table, or summary output.
|
|
113
|
+
stderr while keeping stdout clean for JSON, YAML, CSV, table, or summary output.
|
|
113
114
|
`--progress-every N` controls how many generated scenarios pass between
|
|
114
115
|
updates.
|
|
115
116
|
|
|
@@ -168,7 +168,7 @@ class CliTests(unittest.TestCase):
|
|
|
168
168
|
self.assertEqual(parsed["surface"], "generic")
|
|
169
169
|
self.assertTrue((target / "SKILL.md").is_file())
|
|
170
170
|
self.assertTrue((target / "references" / "modeling-rules.md").is_file())
|
|
171
|
-
self.assertIn("
|
|
171
|
+
self.assertIn("do not strip them and mark invalid rows downstream", (target / "SKILL.md").read_text())
|
|
172
172
|
self.assertIn(
|
|
173
173
|
"mark them invalid downstream",
|
|
174
174
|
(target / "references" / "modeling-rules.md").read_text(),
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
import unittest
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import yaml
|
|
11
|
+
|
|
12
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
13
|
+
FIXTURES = ROOT / "tests" / "fixtures"
|
|
14
|
+
sys.path.insert(0, str(ROOT / "src"))
|
|
15
|
+
|
|
16
|
+
from lattice.formatters import _yaml_string, format_json, format_yaml, render_output
|
|
17
|
+
from lattice.ipog import GenerationResult, generate_covering_array
|
|
18
|
+
from lattice.parser import load_model
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def uescape(hex_digits: str) -> str:
|
|
22
|
+
# Built in pieces so the source stays ASCII.
|
|
23
|
+
return '"' + "\\" + "u" + hex_digits + '"'
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def quoted(*code_points: int) -> str:
|
|
27
|
+
return '"' + "".join(chr(point) for point in code_points) + '"'
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class YamlFormatTests(unittest.TestCase):
|
|
31
|
+
"""`--format yaml`: the same content as `--format json`, written by hand.
|
|
32
|
+
|
|
33
|
+
tests/fixtures/yaml_edges.golden.yaml pins the exact bytes for
|
|
34
|
+
tests/fixtures/yaml_edges.json; the Ruby gem (latticerb) tests against
|
|
35
|
+
the same pair.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def generate(self, fixture: str):
|
|
39
|
+
model = load_model(str(FIXTURES / fixture))
|
|
40
|
+
return model, generate_covering_array(model, strength=model.strength, seed=42, pool_size=50)
|
|
41
|
+
|
|
42
|
+
def test_edge_case_fixture_matches_golden_bytes(self) -> None:
|
|
43
|
+
model, result = self.generate("yaml_edges.json")
|
|
44
|
+
golden = (FIXTURES / "yaml_edges.golden.yaml").read_text(encoding="utf-8")
|
|
45
|
+
self.assertEqual(format_yaml(model, result, seed=42) + "\n", golden)
|
|
46
|
+
|
|
47
|
+
def test_yaml_reads_back_as_the_json_payload(self) -> None:
|
|
48
|
+
for fixture in ("simple.json", "constrained.json", "skillit.json", "yaml_edges.json"):
|
|
49
|
+
with self.subTest(fixture=fixture):
|
|
50
|
+
model, result = self.generate(fixture)
|
|
51
|
+
self.assertEqual(
|
|
52
|
+
yaml.safe_load(format_yaml(model, result, seed=42)),
|
|
53
|
+
json.loads(format_json(model, result, seed=42)),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def test_empty_result_writes_empty_lists_and_null_seed(self) -> None:
|
|
57
|
+
model = load_model(str(FIXTURES / "simple.json"))
|
|
58
|
+
result = GenerationResult(rows=(), coverage_curve=(), total_valid_tuples=0)
|
|
59
|
+
expected = "\n".join(
|
|
60
|
+
[
|
|
61
|
+
"meta:",
|
|
62
|
+
' model_name: "simple"',
|
|
63
|
+
" strength: 2",
|
|
64
|
+
" test_count: 0",
|
|
65
|
+
" exhaustive_count: 8",
|
|
66
|
+
' reduction: "inf"',
|
|
67
|
+
' coverage: "0.0%"',
|
|
68
|
+
" seed: null",
|
|
69
|
+
"coverage_curve: []",
|
|
70
|
+
"scenarios: []",
|
|
71
|
+
]
|
|
72
|
+
)
|
|
73
|
+
self.assertEqual(render_output(model, result, output_format="yaml", seed=None), expected)
|
|
74
|
+
|
|
75
|
+
def test_yaml_string_escapes(self) -> None:
|
|
76
|
+
backslash = "\\"
|
|
77
|
+
cases = {
|
|
78
|
+
"plain": '"plain"',
|
|
79
|
+
"": '""',
|
|
80
|
+
"yes": '"yes"',
|
|
81
|
+
"~": '"~"',
|
|
82
|
+
'say "hi"': '"say ' + backslash + '"hi' + backslash + '""',
|
|
83
|
+
"back" + backslash + "slash": '"back' + backslash * 2 + 'slash"',
|
|
84
|
+
chr(0x08): '"' + backslash + 'b"',
|
|
85
|
+
chr(0x09): '"' + backslash + 't"',
|
|
86
|
+
chr(0x0A): '"' + backslash + 'n"',
|
|
87
|
+
chr(0x0C): '"' + backslash + 'f"',
|
|
88
|
+
chr(0x0D): '"' + backslash + 'r"',
|
|
89
|
+
chr(0x00): uescape("0000"),
|
|
90
|
+
chr(0x07): uescape("0007"),
|
|
91
|
+
chr(0x0B): uescape("000b"),
|
|
92
|
+
chr(0x1F): uescape("001f"),
|
|
93
|
+
chr(0x7E): '"~"',
|
|
94
|
+
chr(0x7F): uescape("007f"),
|
|
95
|
+
chr(0x80): uescape("0080"),
|
|
96
|
+
chr(0x85): uescape("0085"),
|
|
97
|
+
chr(0x9F): uescape("009f"),
|
|
98
|
+
chr(0xA0): quoted(0xA0),
|
|
99
|
+
"caf" + chr(0xE9): quoted(0x63, 0x61, 0x66, 0xE9),
|
|
100
|
+
chr(0x2027): quoted(0x2027),
|
|
101
|
+
chr(0x2028): uescape("2028"),
|
|
102
|
+
chr(0x2029): uescape("2029"),
|
|
103
|
+
chr(0x202A): quoted(0x202A),
|
|
104
|
+
chr(0xFEFF): uescape("feff"),
|
|
105
|
+
chr(0xFFFD): quoted(0xFFFD),
|
|
106
|
+
chr(0xFFFE): uescape("fffe"),
|
|
107
|
+
chr(0xFFFF): uescape("ffff"),
|
|
108
|
+
chr(0x1F600): quoted(0x1F600),
|
|
109
|
+
}
|
|
110
|
+
for value, expected in cases.items():
|
|
111
|
+
with self.subTest(value=ascii(value)):
|
|
112
|
+
self.assertEqual(_yaml_string(value), expected)
|
|
113
|
+
|
|
114
|
+
def test_cli_generate_format_yaml(self) -> None:
|
|
115
|
+
env = dict(os.environ)
|
|
116
|
+
env["PYTHONPATH"] = str(ROOT / "src")
|
|
117
|
+
env["PYTHONIOENCODING"] = "utf-8"
|
|
118
|
+
result = subprocess.run(
|
|
119
|
+
[sys.executable, "-m", "lattice", "generate", "--format", "yaml", str(FIXTURES / "yaml_edges.json")],
|
|
120
|
+
cwd=ROOT,
|
|
121
|
+
env=env,
|
|
122
|
+
capture_output=True,
|
|
123
|
+
check=False,
|
|
124
|
+
)
|
|
125
|
+
self.assertEqual(result.returncode, 0, msg=result.stderr)
|
|
126
|
+
self.assertEqual(result.stdout, (FIXTURES / "yaml_edges.golden.yaml").read_bytes())
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
if __name__ == "__main__":
|
|
130
|
+
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/claude/lattice-workflow/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/codex/lattice-workflow/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lattice_cli-0.1.2 → lattice_cli-0.2.0}/src/lattice/resources/generic/lattice-workflow/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|