@pieai/pro-gov 0.3.9 → 0.3.11
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 +14 -2
- package/assets/docs/reference/adoption/adoption-playbook.md +36 -1
- package/assets/starter/.agents/hooks.json +2 -2
- package/dist/cli.js +280 -84
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -149,8 +149,20 @@ Compound Gate: skipped -> <reason>
|
|
|
149
149
|
```
|
|
150
150
|
|
|
151
151
|
Use `pro-gov doctor --strict-hooks` after syncing an engineering project to
|
|
152
|
-
verify that the host configs are wired.
|
|
153
|
-
|
|
152
|
+
verify that the host configs are wired. This is a wiring check: it proves the
|
|
153
|
+
project calls `pro-gov host-hook` for Codex, Claude Code, and Antigravity. The
|
|
154
|
+
host behavior contract is covered by PGS package tests against recorded
|
|
155
|
+
per-host Stop/SubagentStop fixtures. Open a fresh AI session after installing or
|
|
156
|
+
changing hooks; old sessions may not reload host configuration.
|
|
157
|
+
|
|
158
|
+
Antigravity hook commands enable `PGS_HOST_HOOK_DEBUG=1` by default in PGS
|
|
159
|
+
starters. The hook writes local diagnostics to `.git/pro-gov-hook-debug/` when
|
|
160
|
+
it is actually invoked, including the input summary, decision, and output JSON.
|
|
161
|
+
This directory lives inside Git's private metadata so it does not dirty the
|
|
162
|
+
worktree. If an Antigravity test does not create a diagnostic file, inspect
|
|
163
|
+
whether the host loaded `.agents/hooks.json` before changing PGS policy.
|
|
164
|
+
`.pro-gov/assets.json` is only an asset-install manifest; its `host` field does
|
|
165
|
+
not control runtime hook dispatch.
|
|
154
166
|
|
|
155
167
|
Ponytail can be installed as an optional complexity adviser. Keep its global mode
|
|
156
168
|
`off`; test `lite` in one isolated task before considering a stronger mode.
|
|
@@ -6,7 +6,7 @@ status: stable
|
|
|
6
6
|
canonical: true
|
|
7
7
|
owner: human
|
|
8
8
|
created: 2026-05-06
|
|
9
|
-
last_reviewed: 2026-
|
|
9
|
+
last_reviewed: 2026-07-02
|
|
10
10
|
domain: adoption
|
|
11
11
|
tags:
|
|
12
12
|
- adoption
|
|
@@ -92,8 +92,17 @@ Current package-based method:
|
|
|
92
92
|
- copy `starter/lefthook.template.yml` to `lefthook.yml` and
|
|
93
93
|
`starter/.github/workflows/docs-check.yml` to `.github/workflows/docs-check.yml`
|
|
94
94
|
when the target project is ready for standard guardrails
|
|
95
|
+
- for an `engineering-runtime` target, install the three host-hook starter files
|
|
96
|
+
or merge their Stop/SubagentStop entries into the target's existing host
|
|
97
|
+
config:
|
|
98
|
+
- `.codex/hooks.json`
|
|
99
|
+
- `.claude/settings.json`
|
|
100
|
+
- `.agents/hooks.json`
|
|
95
101
|
- run `doc-gov doctor` after wiring guardrails to verify they are actually
|
|
96
102
|
connected
|
|
103
|
+
- run `pro-gov doctor --strict-hooks` after wiring host hooks to prove the
|
|
104
|
+
target has the expected host-hook configuration for Codex, Claude Code, and
|
|
105
|
+
Antigravity
|
|
97
106
|
- treat the npm package as the CLI source and the local `docs/governance/`
|
|
98
107
|
files as the project's checked-in governance contract
|
|
99
108
|
|
|
@@ -198,6 +207,16 @@ Use Compound Engineering by default only as the post-work Compound Gate:
|
|
|
198
207
|
`ce-compound` captures reusable lessons when they exist; otherwise the agent
|
|
199
208
|
reports a skip reason. Full CE workflows require an explicit user request.
|
|
200
209
|
|
|
210
|
+
The host-hook gate is deliberately small. It does not make Compound Engineering
|
|
211
|
+
the main workflow. It only blocks a final completion report that looks like
|
|
212
|
+
finished engineering work but does not say whether the Compound Gate ran or was
|
|
213
|
+
skipped:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
Compound Gate: ran ce-compound -> <path>
|
|
217
|
+
Compound Gate: skipped -> <reason>
|
|
218
|
+
```
|
|
219
|
+
|
|
201
220
|
### Doc-Only
|
|
202
221
|
|
|
203
222
|
Add:
|
|
@@ -257,6 +276,7 @@ For the v0.9 structural migration, use
|
|
|
257
276
|
Minimum:
|
|
258
277
|
|
|
259
278
|
```bash
|
|
279
|
+
pnpm pro-gov doctor --strict-hooks
|
|
260
280
|
pnpm doc-gov check
|
|
261
281
|
pnpm doc-gov router-check
|
|
262
282
|
pnpm doc-gov scan --check
|
|
@@ -266,6 +286,21 @@ pnpm doc-gov doctor
|
|
|
266
286
|
git diff --check
|
|
267
287
|
```
|
|
268
288
|
|
|
289
|
+
Use `pro-gov doctor --strict-hooks` for engineering-runtime projects. Doc-only
|
|
290
|
+
projects may omit strict host hooks unless they intentionally adopt the
|
|
291
|
+
engineering runtime profile.
|
|
292
|
+
|
|
293
|
+
`pro-gov doctor --strict-hooks` is a wiring check, not a live host simulation.
|
|
294
|
+
It proves the project has hook files that call `pro-gov host-hook`; PGS package
|
|
295
|
+
tests prove the expected Stop/SubagentStop behavior for the supported host
|
|
296
|
+
schemas. After installing or changing hooks, validate from a fresh AI session.
|
|
297
|
+
For Antigravity, a real invocation writes diagnostics under
|
|
298
|
+
`.git/pro-gov-hook-debug/` because the starter hook command sets
|
|
299
|
+
`PGS_HOST_HOOK_DEBUG=1`. Absence of a diagnostic file after a fresh
|
|
300
|
+
Antigravity session usually means the host did not load or run
|
|
301
|
+
`.agents/hooks.json`. The `.pro-gov/assets.json` `host` field records asset
|
|
302
|
+
placement only; it does not control runtime hook dispatch.
|
|
303
|
+
|
|
269
304
|
Engineering projects should also run their local verification ladder.
|
|
270
305
|
|
|
271
306
|
## Example: Migrating A Runtime Product
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"hooks": [
|
|
6
6
|
{
|
|
7
7
|
"type": "command",
|
|
8
|
-
"command": "cd \"$(git rev-parse --show-toplevel)\" && if [ -x ./node_modules/.bin/pro-gov ]; then ./node_modules/.bin/pro-gov host-hook --host antigravity --event Stop; elif [ -f packages/pro-gov/src/cli.ts ] && command -v pnpm >/dev/null 2>&1; then pnpm --silent --filter @pieai/pro-gov dev host-hook --host antigravity --event Stop; else npx --no-install @pieai/pro-gov host-hook --host antigravity --event Stop; fi",
|
|
8
|
+
"command": "cd \"$(git rev-parse --show-toplevel)\" && if [ -x ./node_modules/.bin/pro-gov ]; then PGS_HOST_HOOK_DEBUG=1 ./node_modules/.bin/pro-gov host-hook --host antigravity --event Stop; elif [ -f packages/pro-gov/src/cli.ts ] && command -v pnpm >/dev/null 2>&1; then PGS_HOST_HOOK_DEBUG=1 pnpm --silent --filter @pieai/pro-gov dev host-hook --host antigravity --event Stop; else PGS_HOST_HOOK_DEBUG=1 npx --no-install @pieai/pro-gov host-hook --host antigravity --event Stop; fi",
|
|
9
9
|
"timeout": 30
|
|
10
10
|
}
|
|
11
11
|
]
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"hooks": [
|
|
17
17
|
{
|
|
18
18
|
"type": "command",
|
|
19
|
-
"command": "cd \"$(git rev-parse --show-toplevel)\" && if [ -x ./node_modules/.bin/pro-gov ]; then ./node_modules/.bin/pro-gov host-hook --host antigravity --event SubagentStop; elif [ -f packages/pro-gov/src/cli.ts ] && command -v pnpm >/dev/null 2>&1; then pnpm --silent --filter @pieai/pro-gov dev host-hook --host antigravity --event SubagentStop; else npx --no-install @pieai/pro-gov host-hook --host antigravity --event SubagentStop; fi",
|
|
19
|
+
"command": "cd \"$(git rev-parse --show-toplevel)\" && if [ -x ./node_modules/.bin/pro-gov ]; then PGS_HOST_HOOK_DEBUG=1 ./node_modules/.bin/pro-gov host-hook --host antigravity --event SubagentStop; elif [ -f packages/pro-gov/src/cli.ts ] && command -v pnpm >/dev/null 2>&1; then PGS_HOST_HOOK_DEBUG=1 pnpm --silent --filter @pieai/pro-gov dev host-hook --host antigravity --event SubagentStop; else PGS_HOST_HOOK_DEBUG=1 npx --no-install @pieai/pro-gov host-hook --host antigravity --event SubagentStop; fi",
|
|
20
20
|
"timeout": 30
|
|
21
21
|
}
|
|
22
22
|
]
|
package/dist/cli.js
CHANGED
|
@@ -1628,6 +1628,9 @@ function checkStrictHostHooks(root) {
|
|
|
1628
1628
|
if (!content.includes("pro-gov host-hook") || !content.includes(`--host ${entry.host}`)) {
|
|
1629
1629
|
issues.push(`host-hooks: ${entry.path} does not call pro-gov host-hook for ${entry.host}`);
|
|
1630
1630
|
}
|
|
1631
|
+
if (entry.host === "antigravity" && !content.includes("PGS_HOST_HOOK_DEBUG=1")) {
|
|
1632
|
+
issues.push(`host-hooks: ${entry.path} does not enable PGS_HOST_HOOK_DEBUG=1 for Antigravity diagnostics`);
|
|
1633
|
+
}
|
|
1631
1634
|
}
|
|
1632
1635
|
return issues;
|
|
1633
1636
|
}
|
|
@@ -1636,15 +1639,23 @@ function isEngineeringRuntimeProject(root) {
|
|
|
1636
1639
|
}
|
|
1637
1640
|
|
|
1638
1641
|
// src/commands/host-hook.ts
|
|
1639
|
-
import {
|
|
1642
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
1643
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "node:fs";
|
|
1644
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
1645
|
+
import { basename as basename3, join as join13, resolve as resolve2 } from "node:path";
|
|
1640
1646
|
|
|
1641
1647
|
// src/host-hooks/host-hook-runner.ts
|
|
1648
|
+
import { closeSync, openSync, readFileSync as readFileSync9, readSync, statSync as statSync3 } from "node:fs";
|
|
1642
1649
|
var gateMarkerPattern = /Compound Gate:\s*(ran ce-compound|skipped)\s*->/i;
|
|
1643
1650
|
var completionSignalPatterns = [
|
|
1644
1651
|
/\b(done|completed|implemented|fixed|verified|validated|shipped|pushed|committed)\b/i,
|
|
1645
1652
|
/\b(tests?|typecheck|build|lint|doctor|pack)\b.*\b(pass|passed|green|succeed|succeeded|ok)\b/i,
|
|
1646
1653
|
/\b(changed|updated|modified|created|deleted|refactored)\b.*\b(files?|docs?|tests?|hooks?|configs?)\b/i,
|
|
1647
|
-
|
|
1654
|
+
/已完成|完成了|修好了|实现了|验证通过|测试通过|已经提交|已经推送|提交并推送|已提交|已推送/
|
|
1655
|
+
];
|
|
1656
|
+
var negativeCompletionSignalPatterns = [
|
|
1657
|
+
/\b(not done|not completed|not implemented|not fixed|did not complete|didn't complete|have not completed|haven't completed)\b/i,
|
|
1658
|
+
/没有完成|未完成|还没完成|没有改动|未改动|没有修改|未修改/
|
|
1648
1659
|
];
|
|
1649
1660
|
var compoundGateInstruction = [
|
|
1650
1661
|
"Before final reporting, pass the PGS Compound Gate.",
|
|
@@ -1653,6 +1664,7 @@ var compoundGateInstruction = [
|
|
|
1653
1664
|
"If there is no reusable learning, report:",
|
|
1654
1665
|
"Compound Gate: skipped -> <reason>"
|
|
1655
1666
|
].join("\n");
|
|
1667
|
+
var maxTranscriptBytes = 2 * 1024 * 1024;
|
|
1656
1668
|
function evaluateHostHook(request) {
|
|
1657
1669
|
if (request.event !== "Stop" && request.event !== "SubagentStop") {
|
|
1658
1670
|
return { action: "allow" };
|
|
@@ -1694,7 +1706,7 @@ function formatHostHookOutput(host, event, decision) {
|
|
|
1694
1706
|
}
|
|
1695
1707
|
if (host === "claude" || host === "claude-code") {
|
|
1696
1708
|
if (event === "Stop" || event === "SubagentStop") {
|
|
1697
|
-
return {
|
|
1709
|
+
return { decision: "block", reason: decision.reason };
|
|
1698
1710
|
}
|
|
1699
1711
|
if (decision.action === "block") {
|
|
1700
1712
|
return {
|
|
@@ -1723,11 +1735,14 @@ function normalizeStopInput(input) {
|
|
|
1723
1735
|
return { lastAssistantMessage: void 0, stopHookActive: false };
|
|
1724
1736
|
}
|
|
1725
1737
|
return {
|
|
1726
|
-
lastAssistantMessage: findString(input, ["last_assistant_message", "lastAssistantMessage", "message", "text"]),
|
|
1738
|
+
lastAssistantMessage: findString(input, ["last_assistant_message", "lastAssistantMessage", "message", "text"]) ?? findLastAssistantMessageFromTranscript(findString(input, ["agent_transcript_path", "agentTranscriptPath"])) ?? findLastAssistantMessageFromTranscript(findString(input, ["transcript_path", "transcriptPath"])),
|
|
1727
1739
|
stopHookActive: findBoolean(input, ["stop_hook_active", "stopHookActive"]) ?? false
|
|
1728
1740
|
};
|
|
1729
1741
|
}
|
|
1730
1742
|
function looksLikeCompletedEngineeringWork(message) {
|
|
1743
|
+
if (negativeCompletionSignalPatterns.some((pattern) => pattern.test(message))) {
|
|
1744
|
+
return false;
|
|
1745
|
+
}
|
|
1731
1746
|
return completionSignalPatterns.some((pattern) => pattern.test(message));
|
|
1732
1747
|
}
|
|
1733
1748
|
function findString(input, keys) {
|
|
@@ -1748,6 +1763,86 @@ function findBoolean(input, keys) {
|
|
|
1748
1763
|
}
|
|
1749
1764
|
return void 0;
|
|
1750
1765
|
}
|
|
1766
|
+
function findLastAssistantMessageFromTranscript(path) {
|
|
1767
|
+
if (!path || path.startsWith("~/")) {
|
|
1768
|
+
return void 0;
|
|
1769
|
+
}
|
|
1770
|
+
let content;
|
|
1771
|
+
try {
|
|
1772
|
+
content = readTranscriptTail(path);
|
|
1773
|
+
} catch {
|
|
1774
|
+
return void 0;
|
|
1775
|
+
}
|
|
1776
|
+
const lines = content.split(/\r?\n/);
|
|
1777
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
1778
|
+
const line = lines[index]?.trim();
|
|
1779
|
+
if (!line) {
|
|
1780
|
+
continue;
|
|
1781
|
+
}
|
|
1782
|
+
let record;
|
|
1783
|
+
try {
|
|
1784
|
+
record = JSON.parse(line);
|
|
1785
|
+
} catch {
|
|
1786
|
+
continue;
|
|
1787
|
+
}
|
|
1788
|
+
const message = extractAssistantText(record);
|
|
1789
|
+
if (message) {
|
|
1790
|
+
return message;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
return void 0;
|
|
1794
|
+
}
|
|
1795
|
+
function readTranscriptTail(path) {
|
|
1796
|
+
const size = statSync3(path).size;
|
|
1797
|
+
if (size <= maxTranscriptBytes) {
|
|
1798
|
+
return readFileSync9(path, "utf8");
|
|
1799
|
+
}
|
|
1800
|
+
const fd = openSync(path, "r");
|
|
1801
|
+
try {
|
|
1802
|
+
const buffer = Buffer.allocUnsafe(maxTranscriptBytes);
|
|
1803
|
+
readSync(fd, buffer, 0, maxTranscriptBytes, size - maxTranscriptBytes);
|
|
1804
|
+
return buffer.toString("utf8");
|
|
1805
|
+
} finally {
|
|
1806
|
+
closeSync(fd);
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
function extractAssistantText(value) {
|
|
1810
|
+
if (!isRecord(value)) {
|
|
1811
|
+
return void 0;
|
|
1812
|
+
}
|
|
1813
|
+
const nested = value.message;
|
|
1814
|
+
const role = findString(value, ["role", "type"]);
|
|
1815
|
+
if (isRecord(nested)) {
|
|
1816
|
+
const nestedRole = findString(nested, ["role", "type"]);
|
|
1817
|
+
if (nestedRole === "assistant") {
|
|
1818
|
+
return extractTextContent(nested.content);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
if (role === "assistant") {
|
|
1822
|
+
return extractTextContent(value.content) ?? extractTextContent(value.text);
|
|
1823
|
+
}
|
|
1824
|
+
return void 0;
|
|
1825
|
+
}
|
|
1826
|
+
function extractTextContent(value) {
|
|
1827
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1828
|
+
return value;
|
|
1829
|
+
}
|
|
1830
|
+
if (!Array.isArray(value)) {
|
|
1831
|
+
return void 0;
|
|
1832
|
+
}
|
|
1833
|
+
const parts = [];
|
|
1834
|
+
for (const item of value) {
|
|
1835
|
+
if (typeof item === "string") {
|
|
1836
|
+
parts.push(item);
|
|
1837
|
+
continue;
|
|
1838
|
+
}
|
|
1839
|
+
if (isRecord(item) && typeof item.text === "string") {
|
|
1840
|
+
parts.push(item.text);
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
const text = parts.join("\n").trim();
|
|
1844
|
+
return text.length > 0 ? text : void 0;
|
|
1845
|
+
}
|
|
1751
1846
|
function isRecord(value) {
|
|
1752
1847
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1753
1848
|
}
|
|
@@ -1761,7 +1856,9 @@ function isHostHookEvent(value) {
|
|
|
1761
1856
|
}
|
|
1762
1857
|
|
|
1763
1858
|
// src/commands/host-hook.ts
|
|
1764
|
-
|
|
1859
|
+
var defaultStdinTimeoutMs = 750;
|
|
1860
|
+
var maxDebugRawInputBytes = 256 * 1024;
|
|
1861
|
+
async function runHostHook(args) {
|
|
1765
1862
|
const host = readOption(args, "--host");
|
|
1766
1863
|
const event = readOption(args, "--event");
|
|
1767
1864
|
if (!isHostHookHost(host)) {
|
|
@@ -1772,9 +1869,18 @@ function runHostHook(args) {
|
|
|
1772
1869
|
console.error("Expected --event <Stop|SubagentStop|PreToolUse|PostToolUse|UserPromptSubmit>");
|
|
1773
1870
|
return 1;
|
|
1774
1871
|
}
|
|
1775
|
-
const
|
|
1872
|
+
const rawInput = await readStdinText(defaultStdinTimeoutMs);
|
|
1873
|
+
const input = parseStdinJson(rawInput);
|
|
1776
1874
|
const decision = evaluateHostHook({ host, event, input });
|
|
1777
1875
|
const output = formatHostHookOutput(host, event, decision);
|
|
1876
|
+
writeDebugLogIfRequested(args, {
|
|
1877
|
+
decision,
|
|
1878
|
+
event,
|
|
1879
|
+
host,
|
|
1880
|
+
input,
|
|
1881
|
+
output,
|
|
1882
|
+
rawInput
|
|
1883
|
+
});
|
|
1778
1884
|
console.log(`${JSON.stringify(output)}
|
|
1779
1885
|
`);
|
|
1780
1886
|
return 0;
|
|
@@ -1784,8 +1890,7 @@ function readOption(args, name) {
|
|
|
1784
1890
|
if (index < 0) return void 0;
|
|
1785
1891
|
return args[index + 1];
|
|
1786
1892
|
}
|
|
1787
|
-
function
|
|
1788
|
-
const raw = readFileSync9(0, "utf8").trim();
|
|
1893
|
+
function parseStdinJson(raw) {
|
|
1789
1894
|
if (!raw) return {};
|
|
1790
1895
|
try {
|
|
1791
1896
|
return JSON.parse(raw);
|
|
@@ -1793,10 +1898,106 @@ function readStdinJson() {
|
|
|
1793
1898
|
return {};
|
|
1794
1899
|
}
|
|
1795
1900
|
}
|
|
1901
|
+
function readStdinText(timeoutMs) {
|
|
1902
|
+
if (process.stdin.isTTY) {
|
|
1903
|
+
return Promise.resolve("");
|
|
1904
|
+
}
|
|
1905
|
+
process.stdin.setEncoding("utf8");
|
|
1906
|
+
return new Promise((resolveText) => {
|
|
1907
|
+
let settled = false;
|
|
1908
|
+
let content = "";
|
|
1909
|
+
const settle = () => {
|
|
1910
|
+
if (settled) return;
|
|
1911
|
+
settled = true;
|
|
1912
|
+
clearTimeout(timer);
|
|
1913
|
+
process.stdin.off("data", onData);
|
|
1914
|
+
process.stdin.off("end", settle);
|
|
1915
|
+
process.stdin.off("error", settle);
|
|
1916
|
+
process.stdin.pause();
|
|
1917
|
+
resolveText(content.trim());
|
|
1918
|
+
};
|
|
1919
|
+
const onData = (chunk) => {
|
|
1920
|
+
content += chunk.toString();
|
|
1921
|
+
};
|
|
1922
|
+
const timer = setTimeout(settle, timeoutMs);
|
|
1923
|
+
timer.unref();
|
|
1924
|
+
process.stdin.on("data", onData);
|
|
1925
|
+
process.stdin.on("end", settle);
|
|
1926
|
+
process.stdin.on("error", settle);
|
|
1927
|
+
process.stdin.resume();
|
|
1928
|
+
});
|
|
1929
|
+
}
|
|
1930
|
+
function writeDebugLogIfRequested(args, record) {
|
|
1931
|
+
const explicitPath = readOption(args, "--debug-log");
|
|
1932
|
+
const enabled = explicitPath !== void 0 || process.env.PGS_HOST_HOOK_DEBUG === "1";
|
|
1933
|
+
if (!enabled) return;
|
|
1934
|
+
const debugDir = explicitPath && explicitPath.trim().length > 0 ? explicitPath : defaultDebugDir();
|
|
1935
|
+
try {
|
|
1936
|
+
mkdirSync4(debugDir, { recursive: true });
|
|
1937
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1938
|
+
const fileName = `${timestamp}-${process.pid}-${record.host}-${record.event}.json`;
|
|
1939
|
+
writeFileSync3(
|
|
1940
|
+
join13(debugDir, fileName),
|
|
1941
|
+
`${JSON.stringify(
|
|
1942
|
+
{
|
|
1943
|
+
schemaVersion: 1,
|
|
1944
|
+
cwd: process.cwd(),
|
|
1945
|
+
event: record.event,
|
|
1946
|
+
host: record.host,
|
|
1947
|
+
nodeVersion: process.version,
|
|
1948
|
+
packageVersion: readPackageVersion(),
|
|
1949
|
+
rawInput: truncateDebugRawInput(record.rawInput),
|
|
1950
|
+
input: record.input,
|
|
1951
|
+
decision: record.decision,
|
|
1952
|
+
output: record.output
|
|
1953
|
+
},
|
|
1954
|
+
null,
|
|
1955
|
+
2
|
|
1956
|
+
)}
|
|
1957
|
+
`,
|
|
1958
|
+
"utf8"
|
|
1959
|
+
);
|
|
1960
|
+
} catch {
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
function defaultDebugDir() {
|
|
1964
|
+
const gitPath = spawnSync3("git", ["rev-parse", "--git-path", "pro-gov-hook-debug"], {
|
|
1965
|
+
encoding: "utf8",
|
|
1966
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1967
|
+
});
|
|
1968
|
+
const value = gitPath.status === 0 ? gitPath.stdout.trim() : "";
|
|
1969
|
+
if (value) {
|
|
1970
|
+
return resolve2(process.cwd(), value);
|
|
1971
|
+
}
|
|
1972
|
+
return join13(tmpdir2(), "pro-gov-hook-debug", basename3(process.cwd()));
|
|
1973
|
+
}
|
|
1974
|
+
function readPackageVersion() {
|
|
1975
|
+
const packageJsonPath = resolvePackageJsonPath();
|
|
1976
|
+
if (!packageJsonPath) return void 0;
|
|
1977
|
+
try {
|
|
1978
|
+
const parsed = JSON.parse(readFileSync10(packageJsonPath, "utf8"));
|
|
1979
|
+
return typeof parsed.version === "string" ? parsed.version : void 0;
|
|
1980
|
+
} catch {
|
|
1981
|
+
return void 0;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
function resolvePackageJsonPath() {
|
|
1985
|
+
const candidates = [
|
|
1986
|
+
resolve2(process.cwd(), "packages/pro-gov/package.json"),
|
|
1987
|
+
resolve2(process.cwd(), "node_modules/@pieai/pro-gov/package.json")
|
|
1988
|
+
];
|
|
1989
|
+
return candidates.find((candidate) => existsSync13(candidate));
|
|
1990
|
+
}
|
|
1991
|
+
function truncateDebugRawInput(value) {
|
|
1992
|
+
const buffer = Buffer.from(value);
|
|
1993
|
+
if (buffer.byteLength <= maxDebugRawInputBytes) return value;
|
|
1994
|
+
return `${buffer.subarray(0, maxDebugRawInputBytes).toString("utf8")}
|
|
1995
|
+
[truncated]`;
|
|
1996
|
+
}
|
|
1796
1997
|
|
|
1797
1998
|
// src/commands/init.ts
|
|
1798
|
-
import { existsSync as
|
|
1799
|
-
import { basename as
|
|
1999
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync4 } from "node:fs";
|
|
2000
|
+
import { basename as basename4, dirname as dirname7, join as join14 } from "node:path";
|
|
1800
2001
|
|
|
1801
2002
|
// src/commands/shared.ts
|
|
1802
2003
|
function planStarterFiles(profile) {
|
|
@@ -1868,7 +2069,7 @@ function runInit(args) {
|
|
|
1868
2069
|
}
|
|
1869
2070
|
function applyStarterFiles(files, profile) {
|
|
1870
2071
|
const root = process.cwd();
|
|
1871
|
-
const conflicts = files.filter((file) =>
|
|
2072
|
+
const conflicts = files.filter((file) => existsSync14(join14(root, file.targetPath)));
|
|
1872
2073
|
if (conflicts.length > 0) {
|
|
1873
2074
|
console.error("pro-gov init is refusing to overwrite existing project files:");
|
|
1874
2075
|
for (const file of conflicts) console.error(` ${file.targetPath}`);
|
|
@@ -1876,11 +2077,11 @@ function applyStarterFiles(files, profile) {
|
|
|
1876
2077
|
return 1;
|
|
1877
2078
|
}
|
|
1878
2079
|
for (const file of files) {
|
|
1879
|
-
const targetPath =
|
|
1880
|
-
|
|
1881
|
-
const source =
|
|
1882
|
-
const content = file.targetPath === "AGENTS.md" ? renderAgentsTemplate(source.toString("utf8"),
|
|
1883
|
-
|
|
2080
|
+
const targetPath = join14(root, file.targetPath);
|
|
2081
|
+
mkdirSync5(dirname7(targetPath), { recursive: true });
|
|
2082
|
+
const source = readFileSync11(file.absoluteSourcePath);
|
|
2083
|
+
const content = file.targetPath === "AGENTS.md" ? renderAgentsTemplate(source.toString("utf8"), basename4(root), profile) : source;
|
|
2084
|
+
writeFileSync4(targetPath, content);
|
|
1884
2085
|
}
|
|
1885
2086
|
console.log("pro-gov init APPLIED");
|
|
1886
2087
|
console.log(`profile: ${profile}`);
|
|
@@ -1908,12 +2109,12 @@ function readFlag(args, flag) {
|
|
|
1908
2109
|
}
|
|
1909
2110
|
|
|
1910
2111
|
// src/commands/lens.ts
|
|
1911
|
-
import { mkdirSync as
|
|
2112
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "node:fs";
|
|
1912
2113
|
import { dirname as dirname9 } from "node:path";
|
|
1913
2114
|
|
|
1914
2115
|
// src/lens/audit.ts
|
|
1915
|
-
import { existsSync as
|
|
1916
|
-
import { basename as
|
|
2116
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "node:fs";
|
|
2117
|
+
import { basename as basename5, dirname as dirname8, join as join15 } from "node:path";
|
|
1917
2118
|
var REQUIRED_ARTIFACTS = [
|
|
1918
2119
|
"manifest.md",
|
|
1919
2120
|
"raw/project-lens/architecture-lens.md",
|
|
@@ -1933,20 +2134,20 @@ function createProjectLensAuditPackage(targetDir, auditDir) {
|
|
|
1933
2134
|
version: 1,
|
|
1934
2135
|
target: {
|
|
1935
2136
|
path: targetDir,
|
|
1936
|
-
name:
|
|
2137
|
+
name: basename5(targetDir) || "target"
|
|
1937
2138
|
},
|
|
1938
2139
|
requiredArtifacts: [...REQUIRED_ARTIFACTS]
|
|
1939
2140
|
};
|
|
1940
|
-
|
|
1941
|
-
writeJson(
|
|
2141
|
+
mkdirSync6(auditDir, { recursive: true });
|
|
2142
|
+
writeJson(join15(auditDir, "audit.contract.json"), contract);
|
|
1942
2143
|
for (const artifactPath of REQUIRED_ARTIFACTS) {
|
|
1943
|
-
writeTemplate(
|
|
2144
|
+
writeTemplate(join15(auditDir, artifactPath), renderArtifactTemplate(artifactPath, contract));
|
|
1944
2145
|
}
|
|
1945
2146
|
return contract;
|
|
1946
2147
|
}
|
|
1947
2148
|
function checkProjectLensAuditPackage(auditDir, options = {}) {
|
|
1948
|
-
const contractPath =
|
|
1949
|
-
if (!
|
|
2149
|
+
const contractPath = join15(auditDir, "audit.contract.json");
|
|
2150
|
+
if (!existsSync15(contractPath)) {
|
|
1950
2151
|
return {
|
|
1951
2152
|
ok: false,
|
|
1952
2153
|
auditDir,
|
|
@@ -1960,7 +2161,7 @@ function checkProjectLensAuditPackage(auditDir, options = {}) {
|
|
|
1960
2161
|
}
|
|
1961
2162
|
let contract;
|
|
1962
2163
|
try {
|
|
1963
|
-
contract = JSON.parse(
|
|
2164
|
+
contract = JSON.parse(readFileSync12(contractPath, "utf8"));
|
|
1964
2165
|
} catch (error) {
|
|
1965
2166
|
return {
|
|
1966
2167
|
ok: false,
|
|
@@ -1993,12 +2194,12 @@ function checkProjectLensAuditPackage(auditDir, options = {}) {
|
|
|
1993
2194
|
}
|
|
1994
2195
|
}
|
|
1995
2196
|
for (const artifactPath of REQUIRED_ARTIFACTS) {
|
|
1996
|
-
const absolutePath =
|
|
1997
|
-
if (!
|
|
2197
|
+
const absolutePath = join15(auditDir, artifactPath);
|
|
2198
|
+
if (!existsSync15(absolutePath)) {
|
|
1998
2199
|
issues.push({ type: "missing-required-artifact", path: artifactPath });
|
|
1999
2200
|
continue;
|
|
2000
2201
|
}
|
|
2001
|
-
const content =
|
|
2202
|
+
const content = readFileSync12(absolutePath, "utf8");
|
|
2002
2203
|
if (isPendingArtifact(content)) {
|
|
2003
2204
|
issues.push({ type: "artifact-not-complete", path: artifactPath });
|
|
2004
2205
|
} else if (hasTemplateBody(content)) {
|
|
@@ -2014,13 +2215,13 @@ function checkProjectLensAuditPackage(auditDir, options = {}) {
|
|
|
2014
2215
|
};
|
|
2015
2216
|
}
|
|
2016
2217
|
function writeJson(path, value) {
|
|
2017
|
-
|
|
2018
|
-
|
|
2218
|
+
mkdirSync6(dirname8(path), { recursive: true });
|
|
2219
|
+
writeFileSync5(path, `${JSON.stringify(value, null, 2)}
|
|
2019
2220
|
`);
|
|
2020
2221
|
}
|
|
2021
2222
|
function writeTemplate(path, content) {
|
|
2022
|
-
|
|
2023
|
-
|
|
2223
|
+
mkdirSync6(dirname8(path), { recursive: true });
|
|
2224
|
+
writeFileSync5(path, content);
|
|
2024
2225
|
}
|
|
2025
2226
|
function renderArtifactTemplate(artifactPath, contract) {
|
|
2026
2227
|
const title = artifactPath.replace(/\.md$/, "").split("/").map((part) => part.replaceAll("-", " ")).join(" / ");
|
|
@@ -2257,9 +2458,9 @@ function bulletList(values) {
|
|
|
2257
2458
|
}
|
|
2258
2459
|
|
|
2259
2460
|
// src/lens/scan.ts
|
|
2260
|
-
import { spawnSync as
|
|
2261
|
-
import { existsSync as
|
|
2262
|
-
import { join as
|
|
2461
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
2462
|
+
import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync as readFileSync13, statSync as statSync4 } from "node:fs";
|
|
2463
|
+
import { join as join16, relative as relative5 } from "node:path";
|
|
2263
2464
|
var ignoredDirectories = /* @__PURE__ */ new Set([
|
|
2264
2465
|
".git",
|
|
2265
2466
|
".next",
|
|
@@ -2276,24 +2477,24 @@ function scanProjectLensTarget(targetDir, options = {}) {
|
|
|
2276
2477
|
return {
|
|
2277
2478
|
targetDir,
|
|
2278
2479
|
aiEntryFiles: ["AGENTS.md", "CLAUDE.md"].filter(
|
|
2279
|
-
(file) =>
|
|
2480
|
+
(file) => existsSync16(join16(targetDir, file))
|
|
2280
2481
|
),
|
|
2281
2482
|
aiConfigFiles: [],
|
|
2282
2483
|
packageJson,
|
|
2283
2484
|
docs: {
|
|
2284
|
-
hasDocsDirectory:
|
|
2485
|
+
hasDocsDirectory: existsSync16(join16(targetDir, "docs")),
|
|
2285
2486
|
markdownFileCount: markdownFiles.length,
|
|
2286
2487
|
governanceFiles: markdownFiles.filter((file) => file.startsWith("docs/governance/") || file.startsWith("docs/policy/")).sort()
|
|
2287
2488
|
},
|
|
2288
2489
|
git: readGitState(targetDir),
|
|
2289
|
-
largeFiles: files.map((file) => ({ path: file, bytes:
|
|
2490
|
+
largeFiles: files.map((file) => ({ path: file, bytes: statSync4(join16(targetDir, file)).size })).filter((file) => file.bytes >= largeFileBytes).sort((a, b) => b.bytes - a.bytes || a.path.localeCompare(b.path)).slice(0, 25)
|
|
2290
2491
|
};
|
|
2291
2492
|
}
|
|
2292
2493
|
function readPackageJson(targetDir) {
|
|
2293
|
-
const packageJsonPath =
|
|
2294
|
-
if (!
|
|
2494
|
+
const packageJsonPath = join16(targetDir, "package.json");
|
|
2495
|
+
if (!existsSync16(packageJsonPath)) return void 0;
|
|
2295
2496
|
try {
|
|
2296
|
-
const packageJson = JSON.parse(
|
|
2497
|
+
const packageJson = JSON.parse(readFileSync13(packageJsonPath, "utf8"));
|
|
2297
2498
|
return {
|
|
2298
2499
|
scripts: Object.keys(packageJson.scripts ?? {}).sort(),
|
|
2299
2500
|
dependencies: Object.keys(packageJson.dependencies ?? {}).sort(),
|
|
@@ -2316,7 +2517,7 @@ function readGitState(targetDir) {
|
|
|
2316
2517
|
};
|
|
2317
2518
|
}
|
|
2318
2519
|
function runGit(targetDir, args) {
|
|
2319
|
-
const result =
|
|
2520
|
+
const result = spawnSync4("git", ["-C", targetDir, ...args], {
|
|
2320
2521
|
encoding: "utf8"
|
|
2321
2522
|
});
|
|
2322
2523
|
if (result.status !== 0) return { ok: false };
|
|
@@ -2328,13 +2529,13 @@ function listProjectFiles(targetDir) {
|
|
|
2328
2529
|
return files.sort();
|
|
2329
2530
|
}
|
|
2330
2531
|
function collectFiles2(rootDir, currentDir, files) {
|
|
2331
|
-
if (!
|
|
2532
|
+
if (!existsSync16(currentDir)) return;
|
|
2332
2533
|
for (const entry of readdirSync6(currentDir, { withFileTypes: true })) {
|
|
2333
2534
|
if (entry.isDirectory()) {
|
|
2334
2535
|
if (ignoredDirectories.has(entry.name)) continue;
|
|
2335
|
-
collectFiles2(rootDir,
|
|
2536
|
+
collectFiles2(rootDir, join16(currentDir, entry.name), files);
|
|
2336
2537
|
} else if (entry.isFile()) {
|
|
2337
|
-
files.push(toUnixPath4(relative5(rootDir,
|
|
2538
|
+
files.push(toUnixPath4(relative5(rootDir, join16(currentDir, entry.name))));
|
|
2338
2539
|
}
|
|
2339
2540
|
}
|
|
2340
2541
|
}
|
|
@@ -2386,8 +2587,8 @@ function runLensReport(args) {
|
|
|
2386
2587
|
}
|
|
2387
2588
|
const report = scanProjectLensTarget(options.value.targetDir);
|
|
2388
2589
|
const markdown = renderProjectLensMarkdownReport(report);
|
|
2389
|
-
|
|
2390
|
-
|
|
2590
|
+
mkdirSync7(dirname9(options.value.outPath), { recursive: true });
|
|
2591
|
+
writeFileSync6(options.value.outPath, markdown);
|
|
2391
2592
|
console.log(`report: ${options.value.outPath}`);
|
|
2392
2593
|
return 0;
|
|
2393
2594
|
}
|
|
@@ -2490,16 +2691,16 @@ function printUsage2() {
|
|
|
2490
2691
|
}
|
|
2491
2692
|
|
|
2492
2693
|
// src/commands/portfolio.ts
|
|
2493
|
-
import { existsSync as
|
|
2494
|
-
import { join as
|
|
2694
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
2695
|
+
import { join as join17 } from "node:path";
|
|
2495
2696
|
|
|
2496
2697
|
// src/portfolio/manifest.ts
|
|
2497
|
-
import { existsSync as
|
|
2498
|
-
import { dirname as dirname10, isAbsolute as isAbsolute3, resolve as
|
|
2698
|
+
import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
|
|
2699
|
+
import { dirname as dirname10, isAbsolute as isAbsolute3, resolve as resolve3 } from "node:path";
|
|
2499
2700
|
function loadPortfolioManifest(configPath) {
|
|
2500
2701
|
let parsed;
|
|
2501
2702
|
try {
|
|
2502
|
-
parsed = JSON.parse(
|
|
2703
|
+
parsed = JSON.parse(readFileSync14(configPath, "utf8"));
|
|
2503
2704
|
} catch (error) {
|
|
2504
2705
|
return {
|
|
2505
2706
|
configPath,
|
|
@@ -2511,7 +2712,7 @@ function loadPortfolioManifest(configPath) {
|
|
|
2511
2712
|
]
|
|
2512
2713
|
};
|
|
2513
2714
|
}
|
|
2514
|
-
const normalized = resolveManifestPaths(parsed, dirname10(
|
|
2715
|
+
const normalized = resolveManifestPaths(parsed, dirname10(resolve3(configPath)));
|
|
2515
2716
|
const issues = validatePortfolioManifest(normalized);
|
|
2516
2717
|
return {
|
|
2517
2718
|
configPath,
|
|
@@ -2525,7 +2726,7 @@ function resolveManifestPaths(value, configDir) {
|
|
|
2525
2726
|
if (!isRecord2(endpoint) || typeof endpoint.path !== "string" || isAbsolute3(endpoint.path)) {
|
|
2526
2727
|
return endpoint;
|
|
2527
2728
|
}
|
|
2528
|
-
return { ...endpoint, path:
|
|
2729
|
+
return { ...endpoint, path: resolve3(configDir, endpoint.path) };
|
|
2529
2730
|
};
|
|
2530
2731
|
return {
|
|
2531
2732
|
...value,
|
|
@@ -2653,7 +2854,7 @@ function validateEndpoint(value, field, issues) {
|
|
|
2653
2854
|
});
|
|
2654
2855
|
return;
|
|
2655
2856
|
}
|
|
2656
|
-
if (!
|
|
2857
|
+
if (!existsSync17(value.path)) {
|
|
2657
2858
|
issues.push({
|
|
2658
2859
|
type: "missing-path",
|
|
2659
2860
|
id: typeof value.id === "string" ? value.id : void 0,
|
|
@@ -2928,8 +3129,8 @@ function isHost2(value) {
|
|
|
2928
3129
|
return value === "codex" || value === "claude-code" || value === "gemini-cli" || value === "antigravity";
|
|
2929
3130
|
}
|
|
2930
3131
|
function findPortfolioAgentAssetsDir(manifest) {
|
|
2931
|
-
const agentAssetsDir = manifest?.executionEngine?.path ?
|
|
2932
|
-
return agentAssetsDir &&
|
|
3132
|
+
const agentAssetsDir = manifest?.executionEngine?.path ? join17(manifest.executionEngine.path, "agent-assets") : void 0;
|
|
3133
|
+
return agentAssetsDir && existsSync18(join17(agentAssetsDir, "registry.json")) ? agentAssetsDir : void 0;
|
|
2933
3134
|
}
|
|
2934
3135
|
function printUsage3() {
|
|
2935
3136
|
console.error("Usage:");
|
|
@@ -2939,8 +3140,8 @@ function printUsage3() {
|
|
|
2939
3140
|
}
|
|
2940
3141
|
|
|
2941
3142
|
// src/commands/sync.ts
|
|
2942
|
-
import { existsSync as
|
|
2943
|
-
import { join as
|
|
3143
|
+
import { existsSync as existsSync19, readFileSync as readFileSync15 } from "node:fs";
|
|
3144
|
+
import { join as join18 } from "node:path";
|
|
2944
3145
|
function runSync(args) {
|
|
2945
3146
|
if (!args.includes("--check")) {
|
|
2946
3147
|
console.error("pro-gov sync is read-only and requires --check.");
|
|
@@ -2967,16 +3168,16 @@ function runSync(args) {
|
|
|
2967
3168
|
console.log("pro-gov sync check");
|
|
2968
3169
|
console.log(`profile: ${profile}`);
|
|
2969
3170
|
for (const file of planStarterFiles(profile)) {
|
|
2970
|
-
const targetPath =
|
|
2971
|
-
if (!
|
|
3171
|
+
const targetPath = join18(process.cwd(), file.targetPath);
|
|
3172
|
+
if (!existsSync19(targetPath)) {
|
|
2972
3173
|
if (file.ownership === "optional-guardrail") continue;
|
|
2973
3174
|
console.log(`missing: ${file.targetPath}`);
|
|
2974
3175
|
differences += 1;
|
|
2975
3176
|
continue;
|
|
2976
3177
|
}
|
|
2977
3178
|
if (file.ownership === "project-local-seed") continue;
|
|
2978
|
-
const source =
|
|
2979
|
-
const target =
|
|
3179
|
+
const source = readFileSync15(file.absoluteSourcePath, "utf8");
|
|
3180
|
+
const target = readFileSync15(targetPath, "utf8");
|
|
2980
3181
|
if (source !== target) {
|
|
2981
3182
|
console.log(`different: ${file.targetPath}`);
|
|
2982
3183
|
differences += 1;
|
|
@@ -2991,7 +3192,7 @@ function runSync(args) {
|
|
|
2991
3192
|
}
|
|
2992
3193
|
function inferInstalledProfile(root) {
|
|
2993
3194
|
const installed = ["engineering-runtime", "doc-only"].filter(
|
|
2994
|
-
(profile) =>
|
|
3195
|
+
(profile) => existsSync19(join18(root, `docs/governance/agents-routing/${profile}-v0.9.md`))
|
|
2995
3196
|
);
|
|
2996
3197
|
return installed.length === 1 ? installed[0] : void 0;
|
|
2997
3198
|
}
|
|
@@ -3025,27 +3226,22 @@ var COMMANDS = [
|
|
|
3025
3226
|
"doctor"
|
|
3026
3227
|
];
|
|
3027
3228
|
var [command, subcommand] = process.argv.slice(2);
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
}
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
} else if (command === "sync") {
|
|
3042
|
-
process.exitCode = runSync(process.argv.slice(3));
|
|
3043
|
-
} else if (command === "doctor") {
|
|
3044
|
-
process.exitCode = runDoctor(process.argv.slice(3));
|
|
3045
|
-
} else {
|
|
3229
|
+
process.exitCode = await main();
|
|
3230
|
+
async function main() {
|
|
3231
|
+
if (!command || command === "--help" || command === "-h") {
|
|
3232
|
+
printHelp();
|
|
3233
|
+
return command ? 0 : 1;
|
|
3234
|
+
}
|
|
3235
|
+
if (command === "assets") return runAssets(process.argv.slice(3));
|
|
3236
|
+
if (command === "lens") return runLens(process.argv.slice(3));
|
|
3237
|
+
if (command === "portfolio") return runPortfolio(process.argv.slice(3));
|
|
3238
|
+
if (command === "host-hook") return runHostHook(process.argv.slice(3));
|
|
3239
|
+
if (command === "init") return runInit(process.argv.slice(3));
|
|
3240
|
+
if (command === "sync") return runSync(process.argv.slice(3));
|
|
3241
|
+
if (command === "doctor") return runDoctor(process.argv.slice(3));
|
|
3046
3242
|
console.error(`Unknown command: ${[command, subcommand].filter(Boolean).join(" ")}`);
|
|
3047
3243
|
printHelp();
|
|
3048
|
-
|
|
3244
|
+
return 1;
|
|
3049
3245
|
}
|
|
3050
3246
|
function printHelp() {
|
|
3051
3247
|
console.log("pro-gov \u2014 project-level distribution kit for Project Governance System");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pieai/pro-gov",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
4
4
|
"description": "Project-level distribution kit for Project Governance System.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@pieai/doc-gov": "^0.3.
|
|
38
|
+
"@pieai/doc-gov": "^0.3.11"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "24.13.2",
|