@grifhinz/logics-manager 2.7.0 → 2.8.0
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 +37 -3
- package/VERSION +1 -1
- package/clients/viewer/browser-host.js +1181 -83
- package/clients/viewer/index.html +1 -0
- package/clients/viewer/viewer.css +291 -1
- package/logics_manager/cli.py +5 -3
- package/logics_manager/flow.py +61 -1
- package/logics_manager/sync.py +47 -19
- package/logics_manager/viewer.py +973 -16
- package/package.json +1 -1
- package/pyproject.toml +1 -1
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
<div class="viewer-settings-menu__heading">Utilities</div>
|
|
66
66
|
<button class="btn" id="viewer-insights" type="button" title="Show corpus insights">Insights</button>
|
|
67
67
|
<button class="btn" id="viewer-health" type="button" title="Show lint and audit health">Health</button>
|
|
68
|
+
<a class="viewer-settings-menu__version" id="viewer-version-link" href="https://github.com/AlexAgo83/logics-manager" target="_blank" rel="noreferrer" title="Open Logics Manager on GitHub">v0.0.0</a>
|
|
68
69
|
</section>
|
|
69
70
|
</div>
|
|
70
71
|
</div>
|
|
@@ -265,6 +265,11 @@
|
|
|
265
265
|
line-height: 1;
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
.viewer-cdx-button-badge--runs {
|
|
269
|
+
background: rgba(245, 158, 11, 0.16);
|
|
270
|
+
color: #f59e0b;
|
|
271
|
+
}
|
|
272
|
+
|
|
268
273
|
.viewer-refresh-menu {
|
|
269
274
|
position: relative;
|
|
270
275
|
display: inline-flex;
|
|
@@ -314,6 +319,19 @@
|
|
|
314
319
|
width: 100%;
|
|
315
320
|
}
|
|
316
321
|
|
|
322
|
+
.viewer-settings-menu__version {
|
|
323
|
+
justify-self: center;
|
|
324
|
+
color: var(--vscode-descriptionForeground, #9da5b4);
|
|
325
|
+
font-size: 11px;
|
|
326
|
+
text-decoration: none;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.viewer-settings-menu__version:hover,
|
|
330
|
+
.viewer-settings-menu__version:focus-visible {
|
|
331
|
+
color: var(--vscode-textLink-foreground, #4ea1ff);
|
|
332
|
+
text-decoration: underline;
|
|
333
|
+
}
|
|
334
|
+
|
|
317
335
|
.viewer-auto-refresh {
|
|
318
336
|
display: inline-flex;
|
|
319
337
|
align-items: center;
|
|
@@ -657,6 +675,44 @@
|
|
|
657
675
|
align-items: start;
|
|
658
676
|
}
|
|
659
677
|
|
|
678
|
+
.viewer-cdx__workspace--missions {
|
|
679
|
+
grid-template-columns: minmax(240px, 0.9fr) minmax(320px, 1.1fr);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
.viewer-git__summary-card {
|
|
683
|
+
display: grid;
|
|
684
|
+
align-content: start;
|
|
685
|
+
gap: 8px;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
.viewer-git__summary-segments {
|
|
689
|
+
display: flex;
|
|
690
|
+
flex-wrap: wrap;
|
|
691
|
+
gap: 6px;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
.viewer-git__summary-segment {
|
|
695
|
+
display: inline-flex;
|
|
696
|
+
align-items: center;
|
|
697
|
+
gap: 6px;
|
|
698
|
+
min-height: 24px;
|
|
699
|
+
border: 1px solid color-mix(in srgb, var(--vscode-panel-border, #333333) 72%, transparent);
|
|
700
|
+
border-radius: 6px;
|
|
701
|
+
padding: 2px 7px;
|
|
702
|
+
background: color-mix(in srgb, var(--vscode-editorWidget-background, #202020) 76%, var(--vscode-textLink-foreground, #4ea1ff));
|
|
703
|
+
font-size: 12px;
|
|
704
|
+
white-space: nowrap;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
.viewer-git__summary-segment span {
|
|
708
|
+
color: var(--vscode-descriptionForeground, #aaaaaa);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
.viewer-git__summary-segment strong {
|
|
712
|
+
color: var(--vscode-foreground, #dddddd);
|
|
713
|
+
font-size: 13px;
|
|
714
|
+
}
|
|
715
|
+
|
|
660
716
|
.viewer-ci {
|
|
661
717
|
display: grid;
|
|
662
718
|
gap: 12px;
|
|
@@ -685,6 +741,15 @@
|
|
|
685
741
|
margin-bottom: 10px;
|
|
686
742
|
}
|
|
687
743
|
|
|
744
|
+
.viewer-ci__heading--actions {
|
|
745
|
+
align-items: flex-start;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
.viewer-ci__heading--actions > div {
|
|
749
|
+
display: grid;
|
|
750
|
+
gap: 4px;
|
|
751
|
+
}
|
|
752
|
+
|
|
688
753
|
.viewer-ci__heading h2 {
|
|
689
754
|
margin: 0;
|
|
690
755
|
font-size: 13px;
|
|
@@ -832,12 +897,113 @@
|
|
|
832
897
|
gap: 8px;
|
|
833
898
|
}
|
|
834
899
|
|
|
900
|
+
.viewer-cdx__row--block {
|
|
901
|
+
display: grid;
|
|
902
|
+
gap: 8px;
|
|
903
|
+
}
|
|
904
|
+
|
|
835
905
|
.viewer-cdx__row strong,
|
|
836
906
|
.viewer-cdx__entity-main > span {
|
|
837
907
|
min-width: 0;
|
|
838
908
|
text-align: right;
|
|
839
909
|
}
|
|
840
910
|
|
|
911
|
+
.viewer-cdx__row--block strong,
|
|
912
|
+
.viewer-cdx__detail-value {
|
|
913
|
+
min-width: 0;
|
|
914
|
+
text-align: left;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
.viewer-cdx__detail-value {
|
|
918
|
+
display: grid;
|
|
919
|
+
gap: 8px;
|
|
920
|
+
color: var(--vscode-editor-foreground, #d4d4d4);
|
|
921
|
+
line-height: 1.45;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
.viewer-cdx__detail-list {
|
|
925
|
+
display: grid;
|
|
926
|
+
gap: 8px;
|
|
927
|
+
margin: 0;
|
|
928
|
+
padding-left: 20px;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
.viewer-cdx__detail-list li {
|
|
932
|
+
min-width: 0;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
.viewer-cdx__detail-code {
|
|
936
|
+
max-width: 100%;
|
|
937
|
+
max-height: 280px;
|
|
938
|
+
overflow: auto;
|
|
939
|
+
margin: 0;
|
|
940
|
+
padding: 8px;
|
|
941
|
+
border-radius: 6px;
|
|
942
|
+
background: var(--vscode-textCodeBlock-background, #111111);
|
|
943
|
+
color: var(--vscode-textPreformat-foreground, #d7ba7d);
|
|
944
|
+
font-size: 11px;
|
|
945
|
+
line-height: 1.45;
|
|
946
|
+
white-space: pre-wrap;
|
|
947
|
+
overflow-wrap: anywhere;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
.viewer-cdx__log-preview {
|
|
951
|
+
display: grid;
|
|
952
|
+
gap: 10px;
|
|
953
|
+
min-width: 0;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
.viewer-cdx__log-structured,
|
|
957
|
+
.viewer-cdx__log-raw {
|
|
958
|
+
min-width: 0;
|
|
959
|
+
border: 1px solid var(--vscode-panel-border, #333333);
|
|
960
|
+
border-radius: 6px;
|
|
961
|
+
background: color-mix(in srgb, var(--vscode-editorWidget-background, #202020) 76%, transparent);
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
.viewer-cdx__log-structured > summary,
|
|
965
|
+
.viewer-cdx__log-raw > summary {
|
|
966
|
+
cursor: pointer;
|
|
967
|
+
padding: 8px 10px;
|
|
968
|
+
color: var(--vscode-descriptionForeground, #aaaaaa);
|
|
969
|
+
font-size: 12px;
|
|
970
|
+
font-weight: 700;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
.viewer-cdx__log-structured > .viewer-cdx__detail-value {
|
|
974
|
+
padding: 0 10px 10px;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
.viewer-cdx__log-content {
|
|
978
|
+
max-height: min(70vh, 760px);
|
|
979
|
+
overflow: auto;
|
|
980
|
+
margin: 0;
|
|
981
|
+
padding: 12px;
|
|
982
|
+
border: 1px solid var(--vscode-panel-border, #333333);
|
|
983
|
+
border-radius: 6px;
|
|
984
|
+
background: var(--vscode-textCodeBlock-background, #111111);
|
|
985
|
+
color: var(--vscode-textPreformat-foreground, #d7ba7d);
|
|
986
|
+
font-size: 12px;
|
|
987
|
+
line-height: 1.45;
|
|
988
|
+
white-space: pre-wrap;
|
|
989
|
+
overflow-wrap: anywhere;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
.viewer-cdx__path-link {
|
|
993
|
+
border: 0;
|
|
994
|
+
padding: 0;
|
|
995
|
+
background: transparent;
|
|
996
|
+
color: var(--vscode-textLink-foreground, #4ea1ff);
|
|
997
|
+
cursor: pointer;
|
|
998
|
+
font: inherit;
|
|
999
|
+
text-align: right;
|
|
1000
|
+
overflow-wrap: anywhere;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.viewer-cdx__path-link:hover {
|
|
1004
|
+
text-decoration: underline;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
841
1007
|
.viewer-cdx__entity-status {
|
|
842
1008
|
display: flex;
|
|
843
1009
|
flex-wrap: wrap;
|
|
@@ -1016,6 +1182,110 @@
|
|
|
1016
1182
|
overflow-wrap: anywhere;
|
|
1017
1183
|
}
|
|
1018
1184
|
|
|
1185
|
+
.viewer-cdx__missions {
|
|
1186
|
+
display: grid;
|
|
1187
|
+
gap: 8px;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
.viewer-cdx__mission {
|
|
1191
|
+
display: grid;
|
|
1192
|
+
gap: 5px;
|
|
1193
|
+
width: 100%;
|
|
1194
|
+
min-width: 0;
|
|
1195
|
+
padding: 10px;
|
|
1196
|
+
border: 1px solid var(--vscode-panel-border, #333333);
|
|
1197
|
+
border-radius: 6px;
|
|
1198
|
+
background: var(--vscode-input-background, #1f1f1f);
|
|
1199
|
+
color: var(--vscode-foreground, #d4d4d4);
|
|
1200
|
+
font: inherit;
|
|
1201
|
+
text-align: left;
|
|
1202
|
+
cursor: pointer;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
.viewer-cdx__mission.is-active {
|
|
1206
|
+
border-color: var(--vscode-focusBorder, #4ea1ff);
|
|
1207
|
+
background: color-mix(in srgb, var(--vscode-input-background, #1f1f1f) 72%, var(--vscode-textLink-foreground, #4ea1ff));
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
.viewer-cdx__mission span,
|
|
1211
|
+
.viewer-cdx__mission em {
|
|
1212
|
+
color: var(--vscode-descriptionForeground, #aaaaaa);
|
|
1213
|
+
font-size: 12px;
|
|
1214
|
+
font-style: normal;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
.viewer-cdx__field {
|
|
1218
|
+
display: grid;
|
|
1219
|
+
gap: 6px;
|
|
1220
|
+
margin-bottom: 10px;
|
|
1221
|
+
color: var(--vscode-descriptionForeground, #aaaaaa);
|
|
1222
|
+
font-size: 12px;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
.viewer-cdx__field select,
|
|
1226
|
+
.viewer-cdx__field input,
|
|
1227
|
+
.viewer-cdx__field textarea {
|
|
1228
|
+
min-width: 0;
|
|
1229
|
+
width: 100%;
|
|
1230
|
+
border: 1px solid var(--vscode-input-border, var(--vscode-panel-border, #333333));
|
|
1231
|
+
border-radius: 4px;
|
|
1232
|
+
padding: 7px 8px;
|
|
1233
|
+
background: var(--vscode-dropdown-background, var(--vscode-input-background, #1f1f1f));
|
|
1234
|
+
color: var(--vscode-dropdown-foreground, var(--vscode-foreground, #d4d4d4));
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
.viewer-cdx__field textarea {
|
|
1238
|
+
resize: vertical;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
.viewer-cdx__field--check {
|
|
1242
|
+
grid-template-columns: 16px minmax(0, 1fr);
|
|
1243
|
+
align-items: center;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
.viewer-cdx__field--check input {
|
|
1247
|
+
width: 16px;
|
|
1248
|
+
height: 16px;
|
|
1249
|
+
padding: 0;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
.viewer-cdx__strengths,
|
|
1253
|
+
.viewer-cdx__actions {
|
|
1254
|
+
display: flex;
|
|
1255
|
+
flex-wrap: wrap;
|
|
1256
|
+
gap: 8px;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
.viewer-cdx__actions {
|
|
1260
|
+
margin-top: 12px;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
.viewer-cdx__code {
|
|
1264
|
+
max-height: 260px;
|
|
1265
|
+
overflow: auto;
|
|
1266
|
+
margin: 0 0 10px;
|
|
1267
|
+
padding: 9px;
|
|
1268
|
+
border-radius: 6px;
|
|
1269
|
+
background: var(--vscode-textCodeBlock-background, #111111);
|
|
1270
|
+
color: var(--vscode-textPreformat-foreground, #d7ba7d);
|
|
1271
|
+
font-size: 12px;
|
|
1272
|
+
white-space: pre-wrap;
|
|
1273
|
+
overflow-wrap: anywhere;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
.viewer-cdx__code--error {
|
|
1277
|
+
color: #ef4444;
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
.viewer-cdx__warnings {
|
|
1281
|
+
display: grid;
|
|
1282
|
+
gap: 5px;
|
|
1283
|
+
margin: 10px 0 0;
|
|
1284
|
+
padding-left: 18px;
|
|
1285
|
+
color: #f59e0b;
|
|
1286
|
+
font-size: 12px;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1019
1289
|
.viewer-cdx__state,
|
|
1020
1290
|
.viewer-cdx__empty {
|
|
1021
1291
|
margin: 0;
|
|
@@ -1023,6 +1293,18 @@
|
|
|
1023
1293
|
overflow-wrap: anywhere;
|
|
1024
1294
|
}
|
|
1025
1295
|
|
|
1296
|
+
.viewer-cdx__state--ok {
|
|
1297
|
+
color: #22c55e;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
.viewer-cdx__state--warn {
|
|
1301
|
+
color: #f59e0b;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
.viewer-cdx__state--bad {
|
|
1305
|
+
color: #ef4444;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1026
1308
|
@media (max-width: 860px) {
|
|
1027
1309
|
.viewer-cdx__workspace {
|
|
1028
1310
|
grid-template-columns: 1fr;
|
|
@@ -1035,11 +1317,15 @@
|
|
|
1035
1317
|
|
|
1036
1318
|
.viewer-git__workspace {
|
|
1037
1319
|
display: grid;
|
|
1038
|
-
grid-template-columns: minmax(120px, 0.45fr) minmax(
|
|
1320
|
+
grid-template-columns: minmax(120px, 0.45fr) minmax(0, 2.2fr);
|
|
1039
1321
|
gap: 12px;
|
|
1040
1322
|
align-items: start;
|
|
1041
1323
|
}
|
|
1042
1324
|
|
|
1325
|
+
.viewer-git__workspace.has-diff-detail {
|
|
1326
|
+
grid-template-columns: minmax(120px, 0.45fr) minmax(220px, 0.9fr) minmax(280px, 1.3fr);
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1043
1329
|
.viewer-git__domains {
|
|
1044
1330
|
display: grid;
|
|
1045
1331
|
gap: 6px;
|
|
@@ -1096,6 +1382,10 @@
|
|
|
1096
1382
|
display: none !important;
|
|
1097
1383
|
}
|
|
1098
1384
|
|
|
1385
|
+
.viewer-git__detail[hidden] {
|
|
1386
|
+
display: none !important;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1099
1389
|
.viewer-git__panel-header {
|
|
1100
1390
|
display: flex;
|
|
1101
1391
|
align-items: center;
|
package/logics_manager/cli.py
CHANGED
|
@@ -77,12 +77,14 @@ def _build_root_help() -> str:
|
|
|
77
77
|
' logics-manager flow new request --title "My request"',
|
|
78
78
|
" logics-manager audit --group-by-doc",
|
|
79
79
|
" logics-manager status",
|
|
80
|
-
" logics-manager
|
|
80
|
+
" logics-manager flow show req_001_example",
|
|
81
|
+
" logics-manager sync context-pack req_001_example task_001_example --format json",
|
|
82
|
+
" logics-manager sync refresh-mermaid-signatures task_001_example",
|
|
81
83
|
" logics-manager mcp tunnel --repo-root . --port 8765",
|
|
82
84
|
"",
|
|
83
85
|
"Workflow authoring:",
|
|
84
86
|
" flow Create, promote, split, close, and finish workflow docs.",
|
|
85
|
-
" Subcommands: new, list, companion, deliver, validate-closeout, repair, closeout, promote, split, close, finish",
|
|
87
|
+
" Subcommands: new, list, show, companion, deliver, validate-closeout, repair, closeout, promote, split, close, finish",
|
|
86
88
|
" sync Maintain generated workflow state and doc metadata.",
|
|
87
89
|
" Subcommands: close-eligible-requests, refresh-mermaid-signatures,",
|
|
88
90
|
" schema-status, read-doc, list-docs, search-docs,",
|
|
@@ -366,7 +368,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
366
368
|
if manager == "npm":
|
|
367
369
|
_print_path_conflict_guidance(_find_executable_paths("logics-manager"))
|
|
368
370
|
return result.returncode
|
|
369
|
-
if command == "flow"
|
|
371
|
+
if command == "flow":
|
|
370
372
|
from .flow import main as flow_main
|
|
371
373
|
|
|
372
374
|
return flow_main(rest)
|
package/logics_manager/flow.py
CHANGED
|
@@ -15,6 +15,7 @@ from .flow_evidence import structured_validation_line as _structured_validation_
|
|
|
15
15
|
from .index import index_payload
|
|
16
16
|
from .lint import expected_workflow_mermaid_signature, lint_payload
|
|
17
17
|
from .path_utils import ensure_relative_to
|
|
18
|
+
from .sync import read_logics_doc_payload
|
|
18
19
|
from .termstyle import colorize_help
|
|
19
20
|
|
|
20
21
|
|
|
@@ -206,6 +207,10 @@ def _build_help() -> str:
|
|
|
206
207
|
" List workflow docs that are still active.",
|
|
207
208
|
" Flags: --kind {all,request,backlog,task}, --format {text,json}",
|
|
208
209
|
"",
|
|
210
|
+
" show <ref>",
|
|
211
|
+
" Show a bounded workflow document view.",
|
|
212
|
+
" Flags: --max-chars, --section, --format {text,json}",
|
|
213
|
+
"",
|
|
209
214
|
" companion <product|architecture>",
|
|
210
215
|
" Create a companion doc from the integrated runtime.",
|
|
211
216
|
" Flags: --title, --source-ref, --request-ref, --backlog-ref, --task-ref, --format {text,json}, --dry-run",
|
|
@@ -251,6 +256,7 @@ def _build_help() -> str:
|
|
|
251
256
|
"Examples:",
|
|
252
257
|
' logics-manager flow new request --title "My request"',
|
|
253
258
|
" logics-manager flow deliver --from-product prod_017_delivery_loop",
|
|
259
|
+
" logics-manager flow show req_001_my_request",
|
|
254
260
|
" logics-manager flow validate-closeout task_003_fix_docs",
|
|
255
261
|
" logics-manager flow repair gates task_003_fix_docs",
|
|
256
262
|
" logics-manager flow closeout task_003_fix_docs --validation \"pytest passed\" --index --lint --audit",
|
|
@@ -338,6 +344,27 @@ def _build_list_help() -> str:
|
|
|
338
344
|
)
|
|
339
345
|
|
|
340
346
|
|
|
347
|
+
def _build_show_help() -> str:
|
|
348
|
+
return "\n".join(
|
|
349
|
+
[
|
|
350
|
+
"Logics Flow Show",
|
|
351
|
+
"Show a bounded workflow document view.",
|
|
352
|
+
"",
|
|
353
|
+
"Usage:",
|
|
354
|
+
" logics-manager flow show <ref-or-path> [args...]",
|
|
355
|
+
"",
|
|
356
|
+
"Flags:",
|
|
357
|
+
" --max-chars",
|
|
358
|
+
" --section",
|
|
359
|
+
" --format {text,json}",
|
|
360
|
+
"",
|
|
361
|
+
"Examples:",
|
|
362
|
+
" logics-manager flow show req_001_my_request",
|
|
363
|
+
" logics-manager flow show task_003_fix_docs --section Validation",
|
|
364
|
+
]
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
|
|
341
368
|
def _build_companion_help() -> str:
|
|
342
369
|
return "\n".join(
|
|
343
370
|
[
|
|
@@ -2214,6 +2241,13 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
2214
2241
|
list_parser.add_argument("--format", choices=("text", "json"), default="text")
|
|
2215
2242
|
list_parser.set_defaults(func=cmd_list)
|
|
2216
2243
|
|
|
2244
|
+
show_parser = sub.add_parser("show", help="Show a bounded workflow document view.")
|
|
2245
|
+
show_parser.add_argument("source")
|
|
2246
|
+
show_parser.add_argument("--max-chars", type=int, default=4000)
|
|
2247
|
+
show_parser.add_argument("--section", action="append", default=[])
|
|
2248
|
+
show_parser.add_argument("--format", choices=("text", "json"), default="text")
|
|
2249
|
+
show_parser.set_defaults(func=cmd_show)
|
|
2250
|
+
|
|
2217
2251
|
companion_parser = sub.add_parser("companion", help="Create a companion doc from the integrated runtime.")
|
|
2218
2252
|
companion_sub = companion_parser.add_subparsers(dest="kind", required=True)
|
|
2219
2253
|
for kind in ("product", "architecture"):
|
|
@@ -2429,6 +2463,22 @@ def cmd_list(args: argparse.Namespace) -> dict[str, object]:
|
|
|
2429
2463
|
return payload
|
|
2430
2464
|
|
|
2431
2465
|
|
|
2466
|
+
def cmd_show(args: argparse.Namespace) -> dict[str, object]:
|
|
2467
|
+
repo_root = _find_repo_root(Path.cwd())
|
|
2468
|
+
max_chars = args.max_chars if args.max_chars > 0 else 4000
|
|
2469
|
+
payload = read_logics_doc_payload(repo_root, args.source, max_chars=min(max_chars, 12000), sections=args.section or None)
|
|
2470
|
+
if args.format == "json":
|
|
2471
|
+
print_payload({"command": "show", **payload}, args.format)
|
|
2472
|
+
else:
|
|
2473
|
+
print(f"{payload['ref']} ({payload['kind']}): {payload['title']}")
|
|
2474
|
+
print(f"- path: {payload['path']}")
|
|
2475
|
+
print(f"- status: {payload['status']}")
|
|
2476
|
+
print(f"- truncated: {payload['truncated']}")
|
|
2477
|
+
print("")
|
|
2478
|
+
print(str(payload["content"]).rstrip())
|
|
2479
|
+
return payload
|
|
2480
|
+
|
|
2481
|
+
|
|
2432
2482
|
def cmd_companion(args: argparse.Namespace) -> dict[str, object]:
|
|
2433
2483
|
repo_root = _find_repo_root(Path.cwd())
|
|
2434
2484
|
request_ref, backlog_ref, task_ref = _resolve_workflow_refs_for_companion(
|
|
@@ -2793,6 +2843,9 @@ def closeout_payload(
|
|
|
2793
2843
|
finish_payload: dict[str, object] | None = None
|
|
2794
2844
|
if not dry_run:
|
|
2795
2845
|
_close_chain_for_kind(repo_root, task_path, DOC_KINDS["task"], dry_run=False, quiet=True)
|
|
2846
|
+
for ref in mermaid_refs:
|
|
2847
|
+
if ref.startswith(f"{DOC_KINDS['request'].prefix}_"):
|
|
2848
|
+
_maybe_close_request_chain(repo_root, ref, dry_run=False, quiet=True)
|
|
2796
2849
|
finish_issues = _verify_finished_task_chain(repo_root, task_path)
|
|
2797
2850
|
if finish_issues:
|
|
2798
2851
|
raise SystemExit("Finish verification failed:\n" + "\n".join(f"- {issue}" for issue in finish_issues))
|
|
@@ -3244,6 +3297,9 @@ def main(argv: list[str]) -> int:
|
|
|
3244
3297
|
if argv[0] == "list" and _help_requested(argv, 1):
|
|
3245
3298
|
_print_help(_build_list_help())
|
|
3246
3299
|
return 0
|
|
3300
|
+
if argv[0] == "show" and _help_requested(argv, 1):
|
|
3301
|
+
_print_help(_build_show_help())
|
|
3302
|
+
return 0
|
|
3247
3303
|
if argv[0] == "companion" and _help_requested(argv, 1):
|
|
3248
3304
|
_print_help(_build_companion_help())
|
|
3249
3305
|
return 0
|
|
@@ -3289,9 +3345,13 @@ def main(argv: list[str]) -> int:
|
|
|
3289
3345
|
if argv[0] == "finish" and len(argv) > 1 and argv[1] == "task" and _help_requested(argv, 2):
|
|
3290
3346
|
_print_help(_build_finish_kind_help(argv[1]))
|
|
3291
3347
|
return 0
|
|
3348
|
+
valid_commands = {"new", "list", "show", "companion", "deliver", "validate-closeout", "repair", "closeout", "promote", "split", "close", "finish"}
|
|
3349
|
+
if argv[0] not in valid_commands:
|
|
3350
|
+
hint = " Use `logics-manager flow show <ref>` to inspect a workflow doc." if argv[0] in {"read", "view", "cat"} else " Run `logics-manager flow --help` for valid commands."
|
|
3351
|
+
raise SystemExit(f"Unsupported flow subcommand: {argv[0]}.{hint}")
|
|
3292
3352
|
parser = build_parser()
|
|
3293
3353
|
args = parser.parse_args(argv)
|
|
3294
|
-
if args.command not in
|
|
3354
|
+
if args.command not in valid_commands:
|
|
3295
3355
|
raise SystemExit("Unsupported flow subcommand for the native CLI slice.")
|
|
3296
3356
|
payload = args.func(args)
|
|
3297
3357
|
if args.command == "validate-closeout" and isinstance(payload, dict) and not payload.get("ok", False):
|
package/logics_manager/sync.py
CHANGED
|
@@ -259,11 +259,23 @@ def _build_context_pack(
|
|
|
259
259
|
profile: str,
|
|
260
260
|
config: dict[str, object] | None = None,
|
|
261
261
|
) -> dict[str, object]:
|
|
262
|
+
seed_refs = [ref for ref in seed_ref.split(",") if ref]
|
|
262
263
|
docs = _load_workflow_docs(repo_root)
|
|
263
|
-
|
|
264
|
-
if
|
|
265
|
-
|
|
266
|
-
|
|
264
|
+
seeds = [docs.get(ref) for ref in seed_refs]
|
|
265
|
+
missing = [ref for ref, doc in zip(seed_refs, seeds) if doc is None]
|
|
266
|
+
if missing:
|
|
267
|
+
raise SystemExit(f"Unknown workflow ref(s): {', '.join(f'`{ref}`' for ref in missing)}.")
|
|
268
|
+
ordered: list[WorkflowDocModel] = []
|
|
269
|
+
seen: set[str] = set()
|
|
270
|
+
per_seed_limit = _context_profile_limit(profile)
|
|
271
|
+
for seed in seeds:
|
|
272
|
+
if seed is None:
|
|
273
|
+
continue
|
|
274
|
+
for doc in _workflow_neighborhood(seed, docs)[:per_seed_limit]:
|
|
275
|
+
if doc.ref in seen:
|
|
276
|
+
continue
|
|
277
|
+
ordered.append(doc)
|
|
278
|
+
seen.add(doc.ref)
|
|
267
279
|
changed_paths = _git_changed_paths(repo_root) if mode == "diff-first" else []
|
|
268
280
|
cache_key = _context_pack_cache_key(
|
|
269
281
|
repo_root,
|
|
@@ -281,7 +293,8 @@ def _build_context_pack(
|
|
|
281
293
|
"ref": seed_ref,
|
|
282
294
|
"mode": mode,
|
|
283
295
|
"profile": profile,
|
|
284
|
-
"
|
|
296
|
+
"refs": seed_refs,
|
|
297
|
+
"budgets": {"max_docs": per_seed_limit * max(1, len(seed_refs)), "max_docs_per_ref": per_seed_limit},
|
|
285
298
|
"changed_paths": changed_paths,
|
|
286
299
|
"docs": pack_docs,
|
|
287
300
|
"estimates": {
|
|
@@ -725,6 +738,8 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
725
738
|
close_eligible.set_defaults(func=cmd_close_eligible_requests)
|
|
726
739
|
|
|
727
740
|
refresh_mermaid = sub.add_parser("refresh-mermaid-signatures", help="Refresh stale workflow Mermaid signatures without rewriting the full diagram body.")
|
|
741
|
+
refresh_mermaid.add_argument("sources", nargs="*", help="Optional workflow refs or paths to scope the refresh.")
|
|
742
|
+
refresh_mermaid.add_argument("--changed-only", action="store_true", help="Refresh only changed workflow docs.")
|
|
728
743
|
refresh_mermaid.add_argument("--format", choices=("text", "json"), default="text")
|
|
729
744
|
refresh_mermaid.add_argument("--dry-run", action="store_true")
|
|
730
745
|
refresh_mermaid.set_defaults(func=cmd_refresh_mermaid_signatures)
|
|
@@ -779,7 +794,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
779
794
|
append_note.set_defaults(func=cmd_append_note)
|
|
780
795
|
|
|
781
796
|
context_pack = sub.add_parser("context-pack", help="Build a compact context pack from workflow docs.")
|
|
782
|
-
context_pack.add_argument("
|
|
797
|
+
context_pack.add_argument("refs", nargs="+", help="Seed workflow ref(s) for the context pack.")
|
|
783
798
|
context_pack.add_argument("--mode", choices=("summary-only", "diff-first", "full"), default="summary-only")
|
|
784
799
|
context_pack.add_argument("--profile", choices=("tiny", "normal", "deep"), default="normal")
|
|
785
800
|
context_pack.add_argument("--out", help="Write the JSON artifact to this relative path.")
|
|
@@ -812,13 +827,14 @@ def _build_help() -> str:
|
|
|
812
827
|
"",
|
|
813
828
|
" refresh-mermaid-signatures",
|
|
814
829
|
" Refresh stale Mermaid signatures without rewriting diagram bodies.",
|
|
815
|
-
"
|
|
830
|
+
" Args: [refs-or-paths...]",
|
|
831
|
+
" Flags: --changed-only, --format {text,json}, --dry-run",
|
|
816
832
|
"",
|
|
817
833
|
" schema-status [sources...]",
|
|
818
834
|
" Report schema-version coverage for selected workflow docs.",
|
|
819
835
|
" Flags: --format {text,json}",
|
|
820
836
|
"",
|
|
821
|
-
" context-pack <
|
|
837
|
+
" context-pack <refs...>",
|
|
822
838
|
" Build a compact JSON context pack from workflow docs.",
|
|
823
839
|
" Flags: --mode {summary-only,diff-first,full}, --profile {tiny,normal,deep}, --out, --format {text,json}, --dry-run",
|
|
824
840
|
"",
|
|
@@ -848,7 +864,7 @@ def _build_help() -> str:
|
|
|
848
864
|
"",
|
|
849
865
|
"Examples:",
|
|
850
866
|
" logics-manager sync schema-status",
|
|
851
|
-
" logics-manager sync context-pack req_001_my_request --out logics/context-pack.json",
|
|
867
|
+
" logics-manager sync context-pack req_001_my_request task_002_fix_bug --out logics/context-pack.json",
|
|
852
868
|
" logics-manager sync export-graph --format json",
|
|
853
869
|
]
|
|
854
870
|
)
|
|
@@ -879,9 +895,10 @@ def _build_subcommand_help(command: str) -> str:
|
|
|
879
895
|
"Refresh stale workflow Mermaid signatures without rewriting diagram bodies.",
|
|
880
896
|
"",
|
|
881
897
|
"Usage:",
|
|
882
|
-
" logics-manager sync refresh-mermaid-signatures [args...]",
|
|
898
|
+
" logics-manager sync refresh-mermaid-signatures [refs-or-paths...] [args...]",
|
|
883
899
|
"",
|
|
884
900
|
"Flags:",
|
|
901
|
+
" --changed-only",
|
|
885
902
|
" --format {text,json}",
|
|
886
903
|
" --dry-run",
|
|
887
904
|
]
|
|
@@ -909,7 +926,7 @@ def _build_subcommand_help(command: str) -> str:
|
|
|
909
926
|
"Build a compact JSON context pack from workflow docs.",
|
|
910
927
|
"",
|
|
911
928
|
"Usage:",
|
|
912
|
-
" logics-manager sync context-pack <
|
|
929
|
+
" logics-manager sync context-pack <refs...> [args...]",
|
|
913
930
|
"",
|
|
914
931
|
"Flags:",
|
|
915
932
|
" --mode {summary-only,diff-first,full}",
|
|
@@ -919,7 +936,7 @@ def _build_subcommand_help(command: str) -> str:
|
|
|
919
936
|
" --dry-run",
|
|
920
937
|
"",
|
|
921
938
|
"Example:",
|
|
922
|
-
" logics-manager sync context-pack req_001_my_request --out logics/context-pack.json",
|
|
939
|
+
" logics-manager sync context-pack req_001_my_request task_002_fix_bug --out logics/context-pack.json",
|
|
923
940
|
]
|
|
924
941
|
)
|
|
925
942
|
if command == "read-doc":
|
|
@@ -1053,17 +1070,26 @@ def cmd_close_eligible_requests(args: argparse.Namespace) -> dict[str, object]:
|
|
|
1053
1070
|
def cmd_refresh_mermaid_signatures(args: argparse.Namespace) -> dict[str, object]:
|
|
1054
1071
|
repo_root = _find_repo_root(Path.cwd())
|
|
1055
1072
|
modified: list[str] = []
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1073
|
+
if args.changed_only:
|
|
1074
|
+
changed_sources = [
|
|
1075
|
+
path
|
|
1076
|
+
for path in _git_changed_paths(repo_root)
|
|
1077
|
+
if path.startswith(("logics/request/", "logics/backlog/", "logics/tasks/")) and path.endswith(".md")
|
|
1078
|
+
]
|
|
1079
|
+
targets = _resolve_target_docs(repo_root, changed_sources)
|
|
1080
|
+
else:
|
|
1081
|
+
targets = _resolve_target_docs(repo_root, args.sources)
|
|
1082
|
+
for kind, path in targets:
|
|
1083
|
+
if refresh_workflow_mermaid_signature_file(path, kind, args.dry_run, repo_root=repo_root):
|
|
1084
|
+
modified.append(path.relative_to(repo_root).as_posix())
|
|
1061
1085
|
|
|
1062
1086
|
payload = {
|
|
1063
1087
|
"command": "sync",
|
|
1064
1088
|
"kind": "refresh-mermaid-signatures",
|
|
1065
1089
|
"repo_root": repo_root.as_posix(),
|
|
1066
1090
|
"modified_files": modified,
|
|
1091
|
+
"scanned_files": [path.relative_to(repo_root).as_posix() for _kind, path in targets],
|
|
1092
|
+
"changed_only": args.changed_only,
|
|
1067
1093
|
"dry_run": args.dry_run,
|
|
1068
1094
|
}
|
|
1069
1095
|
if args.format == "json":
|
|
@@ -1106,6 +1132,8 @@ def cmd_read_doc(args: argparse.Namespace) -> dict[str, object]:
|
|
|
1106
1132
|
print(f"- path: {payload['path']}")
|
|
1107
1133
|
print(f"- status: {payload['status']}")
|
|
1108
1134
|
print(f"- truncated: {payload['truncated']}")
|
|
1135
|
+
print("")
|
|
1136
|
+
print(str(payload["content"]).rstrip())
|
|
1109
1137
|
return {"command": "sync", "kind": "read-doc", "repo_root": repo_root.as_posix(), **payload}
|
|
1110
1138
|
|
|
1111
1139
|
|
|
@@ -1172,7 +1200,7 @@ def cmd_append_note(args: argparse.Namespace) -> dict[str, object]:
|
|
|
1172
1200
|
|
|
1173
1201
|
def cmd_context_pack(args: argparse.Namespace) -> dict[str, object]:
|
|
1174
1202
|
repo_root = _find_repo_root(Path.cwd())
|
|
1175
|
-
payload = _build_context_pack(repo_root, args.
|
|
1203
|
+
payload = _build_context_pack(repo_root, ",".join(args.refs), mode=args.mode, profile=args.profile, config=None)
|
|
1176
1204
|
if args.out:
|
|
1177
1205
|
out_path, output_path = resolve_repo_output_path(repo_root, args.out)
|
|
1178
1206
|
serialized = json.dumps(payload, indent=2, sort_keys=True) + "\n"
|
|
@@ -1188,7 +1216,7 @@ def cmd_context_pack(args: argparse.Namespace) -> dict[str, object]:
|
|
|
1188
1216
|
if args.format == "json":
|
|
1189
1217
|
print(json.dumps(payload, indent=2, sort_keys=True))
|
|
1190
1218
|
else:
|
|
1191
|
-
print(f"Context pack: {
|
|
1219
|
+
print(f"Context pack: {', '.join(args.refs)} ({payload['mode']}, {payload['profile']})")
|
|
1192
1220
|
print(f"- docs: {payload['estimates']['doc_count']}")
|
|
1193
1221
|
return {"command": "sync", "kind": "context-pack", "repo_root": repo_root.as_posix(), **payload}
|
|
1194
1222
|
|