@grifhinz/logics-manager 2.1.1 → 2.2.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 +80 -5
- package/VERSION +1 -1
- package/logics_manager/assist.py +185 -21
- package/logics_manager/audit.py +72 -18
- package/logics_manager/cli.py +162 -61
- package/logics_manager/cli_output.py +18 -0
- package/logics_manager/flow.py +1257 -83
- package/logics_manager/index.py +3 -7
- package/logics_manager/insights.py +418 -0
- package/logics_manager/lint.py +21 -7
- package/logics_manager/mcp.py +385 -27
- package/logics_manager/path_utils.py +31 -0
- package/logics_manager/sync.py +24 -12
- package/package.json +2 -1
- package/pyproject.toml +1 -1
- package/scripts/npm/logics-manager.mjs +13 -1
package/logics_manager/sync.py
CHANGED
|
@@ -10,6 +10,7 @@ from pathlib import Path
|
|
|
10
10
|
|
|
11
11
|
from .config import find_repo_root
|
|
12
12
|
from .lint import expected_workflow_mermaid_signature
|
|
13
|
+
from .path_utils import resolve_repo_output_path
|
|
13
14
|
from .termstyle import colorize_help
|
|
14
15
|
|
|
15
16
|
|
|
@@ -576,9 +577,10 @@ def append_workflow_note_payload(repo_root: Path, source: str, *, note_kind: str
|
|
|
576
577
|
changed = False
|
|
577
578
|
else:
|
|
578
579
|
lines.insert(insert_at, bullet)
|
|
580
|
+
mermaid_signature_refreshed = False
|
|
579
581
|
if changed and not dry_run:
|
|
580
582
|
path.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8")
|
|
581
|
-
refresh_workflow_mermaid_signature_file(path, kind, dry_run=False, repo_root=repo_root)
|
|
583
|
+
mermaid_signature_refreshed = refresh_workflow_mermaid_signature_file(path, kind, dry_run=False, repo_root=repo_root)
|
|
582
584
|
return {
|
|
583
585
|
"path": path.relative_to(repo_root).as_posix(),
|
|
584
586
|
"ref": path.stem,
|
|
@@ -586,6 +588,7 @@ def append_workflow_note_payload(repo_root: Path, source: str, *, note_kind: str
|
|
|
586
588
|
"section": section,
|
|
587
589
|
"text": cleaned,
|
|
588
590
|
"changed": changed,
|
|
591
|
+
"mermaid_signature_refreshed": mermaid_signature_refreshed,
|
|
589
592
|
"dry_run": dry_run,
|
|
590
593
|
}
|
|
591
594
|
|
|
@@ -689,7 +692,7 @@ def refresh_workflow_mermaid_signature_file(path: Path, kind: str, dry_run: bool
|
|
|
689
692
|
return True
|
|
690
693
|
|
|
691
694
|
|
|
692
|
-
def _close_eligible_requests(repo_root: Path, dry_run: bool) -> tuple[int, int]:
|
|
695
|
+
def _close_eligible_requests(repo_root: Path, dry_run: bool, *, quiet: bool = False) -> tuple[int, int]:
|
|
693
696
|
request_dir = repo_root / DOC_KINDS["request"]["directory"]
|
|
694
697
|
closed = 0
|
|
695
698
|
scanned = 0
|
|
@@ -703,7 +706,8 @@ def _close_eligible_requests(repo_root: Path, dry_run: bool) -> tuple[int, int]:
|
|
|
703
706
|
continue
|
|
704
707
|
if all(_is_doc_done(item_path, "backlog") for item_path in linked_items):
|
|
705
708
|
_close_doc(request_path, "request", dry_run)
|
|
706
|
-
|
|
709
|
+
if not quiet:
|
|
710
|
+
print(f"Auto-closed request {request_ref} (all linked backlog items are done).")
|
|
707
711
|
closed += 1
|
|
708
712
|
return scanned, closed
|
|
709
713
|
|
|
@@ -1030,7 +1034,7 @@ def _print_help(text: str) -> None:
|
|
|
1030
1034
|
|
|
1031
1035
|
def cmd_close_eligible_requests(args: argparse.Namespace) -> dict[str, object]:
|
|
1032
1036
|
repo_root = _find_repo_root(Path.cwd())
|
|
1033
|
-
scanned, closed = _close_eligible_requests(repo_root, args.dry_run)
|
|
1037
|
+
scanned, closed = _close_eligible_requests(repo_root, args.dry_run, quiet=args.format == "json")
|
|
1034
1038
|
payload = {
|
|
1035
1039
|
"command": "sync",
|
|
1036
1040
|
"kind": "close-eligible-requests",
|
|
@@ -1161,6 +1165,8 @@ def cmd_append_note(args: argparse.Namespace) -> dict[str, object]:
|
|
|
1161
1165
|
print(json.dumps(payload, indent=2, sort_keys=True))
|
|
1162
1166
|
else:
|
|
1163
1167
|
print(f"Appended {args.section} note to {payload['path']} (changed: {payload['changed']}).")
|
|
1168
|
+
if payload.get("mermaid_signature_refreshed"):
|
|
1169
|
+
print("- Mermaid signature refreshed.")
|
|
1164
1170
|
return {"command": "sync", "kind": "append-note", "repo_root": repo_root.as_posix(), **payload}
|
|
1165
1171
|
|
|
1166
1172
|
|
|
@@ -1168,13 +1174,16 @@ def cmd_context_pack(args: argparse.Namespace) -> dict[str, object]:
|
|
|
1168
1174
|
repo_root = _find_repo_root(Path.cwd())
|
|
1169
1175
|
payload = _build_context_pack(repo_root, args.ref, mode=args.mode, profile=args.profile, config=None)
|
|
1170
1176
|
if args.out:
|
|
1171
|
-
out_path = (repo_root
|
|
1177
|
+
out_path, output_path = resolve_repo_output_path(repo_root, args.out)
|
|
1172
1178
|
serialized = json.dumps(payload, indent=2, sort_keys=True) + "\n"
|
|
1173
|
-
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1174
1179
|
if not args.dry_run:
|
|
1180
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1175
1181
|
out_path.write_text(serialized, encoding="utf-8")
|
|
1176
|
-
|
|
1177
|
-
|
|
1182
|
+
payload["output_path"] = output_path
|
|
1183
|
+
if args.format == "json":
|
|
1184
|
+
print(json.dumps(payload, indent=2, sort_keys=True))
|
|
1185
|
+
else:
|
|
1186
|
+
print(f"Wrote {output_path}")
|
|
1178
1187
|
else:
|
|
1179
1188
|
if args.format == "json":
|
|
1180
1189
|
print(json.dumps(payload, indent=2, sort_keys=True))
|
|
@@ -1189,13 +1198,16 @@ def cmd_export_graph(args: argparse.Namespace) -> dict[str, object]:
|
|
|
1189
1198
|
payload = _graph_payload(repo_root, config=None)
|
|
1190
1199
|
payload["repo_root"] = repo_root.as_posix()
|
|
1191
1200
|
if args.out:
|
|
1192
|
-
out_path = (repo_root
|
|
1201
|
+
out_path, output_path = resolve_repo_output_path(repo_root, args.out)
|
|
1193
1202
|
serialized = json.dumps(payload, indent=2, sort_keys=True) + "\n"
|
|
1194
|
-
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1195
1203
|
if not args.dry_run:
|
|
1204
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1196
1205
|
out_path.write_text(serialized, encoding="utf-8")
|
|
1197
|
-
|
|
1198
|
-
|
|
1206
|
+
payload["output_path"] = output_path
|
|
1207
|
+
if args.format == "json":
|
|
1208
|
+
print(json.dumps(payload, indent=2, sort_keys=True))
|
|
1209
|
+
else:
|
|
1210
|
+
print(f"Wrote {output_path}")
|
|
1199
1211
|
else:
|
|
1200
1212
|
if args.format == "json":
|
|
1201
1213
|
print(json.dumps(payload, indent=2, sort_keys=True))
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@grifhinz/logics-manager",
|
|
3
3
|
"displayName": "Logics Orchestrator",
|
|
4
4
|
"description": "Visual orchestration for Logics workflows inside VS Code.",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.2.0",
|
|
6
6
|
"publisher": "cdx-logics",
|
|
7
7
|
"icon": "media/icon.png",
|
|
8
8
|
"repository": {
|
|
@@ -130,6 +130,7 @@
|
|
|
130
130
|
"lint:es": "eslint src/**/*.ts",
|
|
131
131
|
"lint:logics": "node scripts/run-python.mjs -m logics_manager lint",
|
|
132
132
|
"audit:logics": "node scripts/run-python.mjs -m logics_manager audit && node scripts/run-python.mjs -m logics_manager lint",
|
|
133
|
+
"audit:logics:strict": "node scripts/run-python.mjs -m logics_manager audit --governance-profile strict && node scripts/run-python.mjs -m logics_manager lint --require-status",
|
|
133
134
|
"audit:ci": "node scripts/check-npm-audit.mjs",
|
|
134
135
|
"logics:finish:task": "node scripts/run-python.mjs -m logics_manager flow finish task",
|
|
135
136
|
"ci:fast": "npm run compile && npm run lint && npm run test:coverage && npm run test:smoke && npm run lint:logics && npm run package:ci",
|
package/pyproject.toml
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { realpathSync } from "node:fs";
|
|
3
4
|
import { dirname, resolve } from "node:path";
|
|
4
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
6
|
|
|
@@ -91,6 +92,17 @@ export function runLogicsManager(argv = process.argv.slice(2), platform = proces
|
|
|
91
92
|
return 1;
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
export function isDirectInvocation(importUrl = import.meta.url, argvPath = process.argv[1]) {
|
|
96
|
+
if (!argvPath) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
return importUrl === pathToFileURL(realpathSync(argvPath)).href;
|
|
101
|
+
} catch {
|
|
102
|
+
return importUrl === pathToFileURL(argvPath).href;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (isDirectInvocation()) {
|
|
95
107
|
process.exit(runLogicsManager());
|
|
96
108
|
}
|