@pieai/pro-gov 0.4.9 → 0.5.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 +2 -2
- package/assets/docs/reference/adoption/adoption-playbook.md +8 -8
- package/assets/docs/reference/adoption/migration-v1.0.md +73 -0
- package/assets/integrations/mattpocock-skills.md +4 -2
- package/assets/portfolio-dashboard/app.js +3 -3
- package/assets/profiles/doc-only/manifest.yml +1 -1
- package/assets/profiles/doc-only/profile.md +2 -2
- package/assets/profiles/engineering-runtime/manifest.yml +1 -1
- package/assets/profiles/engineering-runtime/profile.md +3 -3
- package/assets/starter/AGENTS.template.md +2 -2
- package/assets/starter/docs/governance/agents-routing/{doc-only-v0.9.md → doc-only-v1.0.md} +4 -4
- package/assets/starter/docs/governance/agents-routing/{engineering-runtime-v0.9.md → engineering-runtime-v1.0.md} +4 -4
- package/assets/starter/docs/governance/boundary.md +6 -4
- package/assets/starter/docs/governance/doc-agent-rules.md +3 -7
- package/assets/starter/docs/governance/doc-types.md +2 -6
- package/assets/starter/docs/governance/{ssot-v0.9.md → ssot-v1.0.md} +12 -9
- package/assets/starter/docs/governance/templates/adr.md +2 -22
- package/assets/starter/docs/reference/documentation-map.md +7 -7
- package/cli-guide.md +2 -2
- package/dist/cli.js +83 -28
- package/package.json +2 -2
- package/assets/starter/docs/decisions/.gitkeep +0 -1
|
@@ -6,7 +6,7 @@ required:
|
|
|
6
6
|
ai_in_the_loop:
|
|
7
7
|
target: docs/policy/shared-rules/ai-in-the-loop.md
|
|
8
8
|
source: external shared-rule SSOT
|
|
9
|
-
agents_routing: docs/governance/agents-routing/doc-only-
|
|
9
|
+
agents_routing: docs/governance/agents-routing/doc-only-v1.0.md
|
|
10
10
|
current_work: docs/reference/execution/current-work.md
|
|
11
11
|
project_local_required:
|
|
12
12
|
- docs/policy/best-practice-for-this-project.md
|
|
@@ -6,9 +6,9 @@ Use for non-runtime projects: IP development, AI media production, research vaul
|
|
|
6
6
|
|
|
7
7
|
- `packages/doc-gov`
|
|
8
8
|
- `packages/pro-gov`
|
|
9
|
-
- `docs/governance/ssot-
|
|
9
|
+
- `docs/governance/ssot-v1.0.md`
|
|
10
10
|
- external AI-in-the-Loop policy linked by target projects under `docs/policy/shared-rules/ai-in-the-loop.md`
|
|
11
|
-
- `docs/governance/agents-routing/doc-only-
|
|
11
|
+
- `docs/governance/agents-routing/doc-only-v1.0.md`
|
|
12
12
|
- starter `docs/governance/` and `docs/policy/` templates
|
|
13
13
|
|
|
14
14
|
## Does Not Include By Default
|
|
@@ -6,7 +6,7 @@ required:
|
|
|
6
6
|
ai_in_the_loop:
|
|
7
7
|
target: docs/policy/shared-rules/ai-in-the-loop.md
|
|
8
8
|
source: external shared-rule SSOT
|
|
9
|
-
agents_routing: docs/governance/agents-routing/engineering-runtime-
|
|
9
|
+
agents_routing: docs/governance/agents-routing/engineering-runtime-v1.0.md
|
|
10
10
|
current_work: docs/reference/execution/current-work.md
|
|
11
11
|
optional:
|
|
12
12
|
mattpocock_skills: integrations/mattpocock-skills.md
|
|
@@ -6,9 +6,9 @@ Use for code-heavy projects: apps, games, runtimes, services, browser products,
|
|
|
6
6
|
|
|
7
7
|
- `packages/doc-gov`
|
|
8
8
|
- `packages/pro-gov`
|
|
9
|
-
- `docs/governance/ssot-
|
|
9
|
+
- `docs/governance/ssot-v1.0.md`
|
|
10
10
|
- external AI-in-the-Loop policy linked by target projects under `docs/policy/shared-rules/ai-in-the-loop.md`
|
|
11
|
-
- `docs/governance/agents-routing/engineering-runtime-
|
|
11
|
+
- `docs/governance/agents-routing/engineering-runtime-v1.0.md`
|
|
12
12
|
- `integrations/mattpocock-skills.md`
|
|
13
13
|
- starter `docs/governance/` and `docs/policy/` templates
|
|
14
14
|
|
|
@@ -41,6 +41,6 @@ guardrails are also consumer-owned when installed; `doc-gov doctor` checks that
|
|
|
41
41
|
their required governance commands remain present.
|
|
42
42
|
|
|
43
43
|
For non-trivial engineering work, run `pro-gov learn recall --query "<task
|
|
44
|
-
summary>"` before changing files so existing `docs/
|
|
44
|
+
summary>"` before changing files so existing `docs/reference/learnings/**` and
|
|
45
45
|
`CONCEPTS.md` lessons can shape the work. After verified work, use the
|
|
46
46
|
`capture-learning` skill only when a reusable lesson exists.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## PGS Router Block
|
|
4
4
|
|
|
5
|
-
<!-- PGS-ROUTER:BEGIN
|
|
5
|
+
<!-- PGS-ROUTER:BEGIN v1.0 -->
|
|
6
6
|
|
|
7
7
|
## Boundary
|
|
8
8
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
## Documentation Tasks
|
|
20
20
|
|
|
21
21
|
When the task creates, edits, moves, deletes, or governs documentation, read
|
|
22
|
-
`docs/governance/boundary.md`, `docs/governance/ssot-
|
|
22
|
+
`docs/governance/boundary.md`, `docs/governance/ssot-v1.0.md`,
|
|
23
23
|
`docs/governance/doc-agent-rules.md`, `docs/governance/doc-types.md`, the
|
|
24
24
|
selected agents routing file, and all Markdown under `docs/policy/**/*.md`.
|
|
25
25
|
That policy set includes subdirectories and symlinked shared-rule files; keep
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
id: GOV-AGENTS-ROUTING-DOC-ONLY-
|
|
3
|
-
title: Doc-Only Agents Routing
|
|
2
|
+
id: GOV-AGENTS-ROUTING-DOC-ONLY-V1-0
|
|
3
|
+
title: Doc-Only Agents Routing v1.0
|
|
4
4
|
type: policy
|
|
5
5
|
status: stable
|
|
6
6
|
canonical: true
|
|
@@ -14,13 +14,13 @@ tags:
|
|
|
14
14
|
- workflow
|
|
15
15
|
pinned: true
|
|
16
16
|
related:
|
|
17
|
-
- GOV-SSOT-
|
|
17
|
+
- GOV-SSOT-V1-0
|
|
18
18
|
- REF-DOC-GOVERNANCE-BOUNDARY
|
|
19
19
|
supersedes: []
|
|
20
20
|
superseded_by: null
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
# Doc-Only Agents Routing
|
|
23
|
+
# Doc-Only Agents Routing v1.0
|
|
24
24
|
|
|
25
25
|
Shared routing algorithm for non-runtime projects such as AI media, IP development, research, and asset governance workspaces.
|
|
26
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
id: GOV-AGENTS-ROUTING-ENGINEERING-RUNTIME-
|
|
3
|
-
title: Engineering Runtime Agents Routing
|
|
2
|
+
id: GOV-AGENTS-ROUTING-ENGINEERING-RUNTIME-V1-0
|
|
3
|
+
title: Engineering Runtime Agents Routing v1.0
|
|
4
4
|
type: policy
|
|
5
5
|
status: stable
|
|
6
6
|
canonical: true
|
|
@@ -14,13 +14,13 @@ tags:
|
|
|
14
14
|
- workflow
|
|
15
15
|
pinned: true
|
|
16
16
|
related:
|
|
17
|
-
- GOV-SSOT-
|
|
17
|
+
- GOV-SSOT-V1-0
|
|
18
18
|
- REF-DOC-GOVERNANCE-BOUNDARY
|
|
19
19
|
supersedes: []
|
|
20
20
|
superseded_by: null
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
# Engineering Runtime Agents Routing
|
|
23
|
+
# Engineering Runtime Agents Routing v1.0
|
|
24
24
|
|
|
25
25
|
Shared routing algorithm for app, game, runtime, and code-heavy projects.
|
|
26
26
|
|
|
@@ -53,13 +53,14 @@ project-specific AI development habits live.
|
|
|
53
53
|
| --- | --- |
|
|
54
54
|
| AI startup entry | `AGENTS.md` |
|
|
55
55
|
| Agent routing algorithm | `docs/governance/agents-routing/` |
|
|
56
|
-
| Governed SSOT rules | `docs/governance/ssot-
|
|
56
|
+
| Governed SSOT rules | `docs/governance/ssot-v1.0.md` |
|
|
57
57
|
| Project AI development practices | `docs/policy/best-practice-for-this-project.md` |
|
|
58
58
|
| Current work index | `docs/reference/execution/current-work.md` |
|
|
59
59
|
| Product or world truth | `docs/canon/` |
|
|
60
|
+
| Durable decisions | `docs/adr/`, the single Matt-compatible decision surface |
|
|
60
61
|
| Active implementation work | `docs/plans/active/` |
|
|
61
62
|
| Completed proof records | `docs/plans/completed/` |
|
|
62
|
-
| Reusable project learnings | `docs/
|
|
63
|
+
| Reusable project learnings | `docs/reference/learnings/**` as governed reference documents |
|
|
63
64
|
| Product artifacts outside governed docs | Project package, workbench, assets, runtime config, or source tree |
|
|
64
65
|
|
|
65
66
|
When unsure, ask this question: is this rule about how the document system works,
|
|
@@ -76,5 +77,6 @@ product packages, workbenches, prompt libraries, source folders, or asset
|
|
|
76
77
|
folders can be product artifacts. Keep those files where the product package
|
|
77
78
|
expects them unless a project explicitly opts them into doc-gov.
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
Matt-native files under `docs/adr/**` and `docs/agents/**` are not governed docs
|
|
81
|
+
by default. `docs/adr/**` is nevertheless the only durable decision surface;
|
|
82
|
+
do not copy ADRs into a second PGS decision directory.
|
|
@@ -42,7 +42,6 @@ If a canonical document exists, update it instead of creating a parallel documen
|
|
|
42
42
|
Use only:
|
|
43
43
|
|
|
44
44
|
- `policy`
|
|
45
|
-
- `decision`
|
|
46
45
|
- `spec`
|
|
47
46
|
- `plan`
|
|
48
47
|
- `canon`
|
|
@@ -57,14 +56,11 @@ Normal documents:
|
|
|
57
56
|
draft -> active -> completed -> stable -> superseded -> archived
|
|
58
57
|
```
|
|
59
58
|
|
|
60
|
-
Decision documents:
|
|
61
|
-
|
|
62
|
-
```text
|
|
63
|
-
proposed -> accepted -> rejected | superseded
|
|
64
|
-
```
|
|
65
|
-
|
|
66
59
|
`completed` is for finished execution records or specs that should no longer appear in active folders.
|
|
67
60
|
|
|
61
|
+
Durable decisions belong only in `docs/adr/**`. They use Matt's concise ADR
|
|
62
|
+
format and remain outside the Doc Gov status machine.
|
|
63
|
+
|
|
68
64
|
## Upstream Rule
|
|
69
65
|
|
|
70
66
|
Do not locally invent doc-gov core changes. Propose core changes upstream in
|
|
@@ -28,7 +28,6 @@ Allowed types:
|
|
|
28
28
|
| Type | Default path |
|
|
29
29
|
| --- | --- |
|
|
30
30
|
| `policy` | `docs/policy/` for project policy; `docs/governance/` for doc-system policy |
|
|
31
|
-
| `decision` | `docs/decisions/` |
|
|
32
31
|
| `spec` | `docs/specs/active/` or `docs/specs/completed/` |
|
|
33
32
|
| `plan` | `docs/plans/active/` or `docs/plans/completed/` |
|
|
34
33
|
| `canon` | `docs/canon/` |
|
|
@@ -43,8 +42,5 @@ Normal documents use:
|
|
|
43
42
|
draft -> active -> completed -> stable -> superseded -> archived
|
|
44
43
|
```
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```text
|
|
49
|
-
proposed -> accepted -> rejected | superseded
|
|
50
|
-
```
|
|
45
|
+
Durable decisions use the Matt-compatible `docs/adr/**` surface and stay
|
|
46
|
+
outside the Doc Gov schema. Do not duplicate them in another decision folder.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
id: GOV-SSOT-
|
|
3
|
-
title: SSOT Documentation Governance Rules
|
|
2
|
+
id: GOV-SSOT-V1-0
|
|
3
|
+
title: SSOT Documentation Governance Rules v1.0
|
|
4
4
|
type: policy
|
|
5
5
|
status: stable
|
|
6
6
|
canonical: true
|
|
@@ -19,7 +19,7 @@ supersedes: []
|
|
|
19
19
|
superseded_by: null
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
-
# SSOT Documentation Governance Rules
|
|
22
|
+
# SSOT Documentation Governance Rules v1.0
|
|
23
23
|
|
|
24
24
|
This rule defines how projects using Project Governance System handle
|
|
25
25
|
**SSOT (Single Source of Truth)** for governed documentation.
|
|
@@ -37,7 +37,7 @@ Project Governance System governs:
|
|
|
37
37
|
- `AGENTS.md` and equivalent AI entry files.
|
|
38
38
|
- Governed Markdown under `docs/**`.
|
|
39
39
|
- Documentation governance rules, agent routing rules, templates, manifests,
|
|
40
|
-
plans, specs,
|
|
40
|
+
plans, specs, references, canon, and archives that live under
|
|
41
41
|
`docs/**`.
|
|
42
42
|
|
|
43
43
|
Project Governance System does **not** automatically govern every Markdown file
|
|
@@ -50,10 +50,12 @@ Markdown.
|
|
|
50
50
|
|
|
51
51
|
Extra governed roots are allowed only when a project explicitly opts in.
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
schema:
|
|
53
|
+
Matt-native and optional-tool artifacts are explicitly outside the default Doc
|
|
54
|
+
Gov schema:
|
|
55
55
|
|
|
56
|
-
- `
|
|
56
|
+
- `CONTEXT.md` and `CONTEXT-MAP.md`
|
|
57
|
+
- `docs/adr/**`
|
|
58
|
+
- `docs/agents/**`
|
|
57
59
|
- `docs/brainstorms/**`
|
|
58
60
|
- `docs/pulse-reports/**`
|
|
59
61
|
|
|
@@ -83,7 +85,7 @@ Before changing docs, look for project-local guidance in this order:
|
|
|
83
85
|
|
|
84
86
|
1. `AGENTS.md`, `CLAUDE.md`, or equivalent AI router/config adapter.
|
|
85
87
|
2. `docs/governance/boundary.md`.
|
|
86
|
-
3. `docs/governance/ssot-
|
|
88
|
+
3. `docs/governance/ssot-v1.0.md`.
|
|
87
89
|
4. `docs/governance/agents-routing/` and the project's selected agents-routing file.
|
|
88
90
|
5. `docs/reference/documentation-map.md`, root `README.md` for human-facing
|
|
89
91
|
orientation, or another project-defined documentation index.
|
|
@@ -114,9 +116,10 @@ works for governed docs:
|
|
|
114
116
|
| Agents-routing rules | `docs/governance/agents-routing/` |
|
|
115
117
|
| Doc-system rules, templates, and manifest | `docs/governance/` |
|
|
116
118
|
| Project AI/development policy | `docs/policy/` |
|
|
119
|
+
| Durable decisions | `docs/adr/`, the single Matt-compatible decision surface outside Doc Gov schema |
|
|
117
120
|
| Product or feature requirement | `docs/specs/` |
|
|
118
121
|
| Step-by-step implementation work | `docs/plans/` |
|
|
119
|
-
| Reusable learning records | `docs/
|
|
122
|
+
| Reusable learning records | `docs/reference/learnings/**`, governed as `reference` documents and recalled on demand |
|
|
120
123
|
| Durable workspace/system truth | `docs/canon/` |
|
|
121
124
|
| How-to guides, architecture maps, tool notes | `docs/reference/` |
|
|
122
125
|
| Retired governed history | `docs/archive/` |
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
id: REPLACE-ME
|
|
3
|
-
title: Replace Me
|
|
4
|
-
type: decision
|
|
5
|
-
status: proposed
|
|
6
|
-
canonical: true
|
|
7
|
-
owner: human
|
|
8
|
-
created: YYYY-MM-DD
|
|
9
|
-
last_reviewed: YYYY-MM-DD
|
|
10
|
-
domain: meta
|
|
11
|
-
tags:
|
|
12
|
-
- replace-me
|
|
13
|
-
pinned: false
|
|
14
|
-
related: []
|
|
15
|
-
---
|
|
1
|
+
# Replace Me
|
|
16
2
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
## Context
|
|
20
|
-
|
|
21
|
-
## Decision
|
|
22
|
-
|
|
23
|
-
## Consequences
|
|
3
|
+
Record the context, decision, and why in one to three sentences.
|
|
@@ -24,10 +24,10 @@ Use `AGENTS.md` for startup reading. It should point agents to:
|
|
|
24
24
|
|
|
25
25
|
- `docs/policy/*.md`
|
|
26
26
|
- `docs/governance/boundary.md`
|
|
27
|
-
- `docs/governance/ssot-
|
|
27
|
+
- `docs/governance/ssot-v1.0.md`
|
|
28
28
|
- `docs/governance/doc-agent-rules.md`
|
|
29
29
|
- `docs/governance/doc-types.md`
|
|
30
|
-
- `docs/governance/agents-routing/<selected-profile>-
|
|
30
|
+
- `docs/governance/agents-routing/<selected-profile>-v1.0.md`
|
|
31
31
|
- `docs/reference/execution/current-work.md`
|
|
32
32
|
|
|
33
33
|
## Areas
|
|
@@ -35,12 +35,12 @@ Use `AGENTS.md` for startup reading. It should point agents to:
|
|
|
35
35
|
| Area | Purpose |
|
|
36
36
|
| --- | --- |
|
|
37
37
|
| `docs/policy/` | Project policy and AI development rules |
|
|
38
|
-
| `docs/
|
|
38
|
+
| `docs/adr/` | The single Matt-compatible durable decision surface, outside Doc Gov schema |
|
|
39
39
|
| `docs/specs/active/` | Active requirements |
|
|
40
40
|
| `docs/specs/completed/` | Completed specs |
|
|
41
41
|
| `docs/plans/active/` | Active implementation plans |
|
|
42
42
|
| `docs/plans/completed/` | Completed execution records |
|
|
43
|
-
| `docs/
|
|
43
|
+
| `docs/reference/learnings/` | Governed reusable learning references, recalled only when relevant |
|
|
44
44
|
| `docs/canon/` | Durable project truth |
|
|
45
45
|
| `docs/reference/` | Guides and references |
|
|
46
46
|
| `docs/archive/` | Retired history |
|
|
@@ -51,6 +51,6 @@ project-package canon, generated media notes, and source-package files stay in
|
|
|
51
51
|
their product/workbench structure unless this project explicitly opts them into
|
|
52
52
|
doc-gov.
|
|
53
53
|
|
|
54
|
-
Optional skills may create `docs/
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
Optional skills may create `docs/brainstorms/**` or `docs/pulse-reports/**` as
|
|
55
|
+
external artifacts. Capture Learning writes governed references under
|
|
56
|
+
`docs/reference/learnings/**`.
|
package/cli-guide.md
CHANGED
|
@@ -48,7 +48,7 @@ commands without requiring byte-for-byte template equality. It infers the
|
|
|
48
48
|
installed profile when exactly one route exists; `--profile` resolves an empty
|
|
49
49
|
or temporarily ambiguous target. PGS does not install or modify AI-host hooks.
|
|
50
50
|
|
|
51
|
-
`learn recall` searches `docs/
|
|
51
|
+
`learn recall` searches `docs/reference/learnings/**` and
|
|
52
52
|
`CONCEPTS.md` in the target repository and returns the most relevant prior
|
|
53
53
|
lessons for the current task. Use it before non-trivial implementation,
|
|
54
54
|
debugging, release, architecture, or portfolio-sync work. It is read-only and
|
|
@@ -56,7 +56,7 @@ does not require a full local PGS checkout.
|
|
|
56
56
|
|
|
57
57
|
`learn capture` is the small native capture path. Use it only after verified
|
|
58
58
|
work produced a reusable lesson that is not already covered by an existing
|
|
59
|
-
`docs/
|
|
59
|
+
`docs/reference/learnings/**` record:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
62
|
pro-gov learn capture \
|
package/dist/cli.js
CHANGED
|
@@ -1654,9 +1654,9 @@ import { createRequire } from "node:module";
|
|
|
1654
1654
|
import { dirname as dirname6, join as join12 } from "node:path";
|
|
1655
1655
|
var REQUIRED_ASSETS = [
|
|
1656
1656
|
"starter/AGENTS.template.md",
|
|
1657
|
-
"starter/docs/governance/ssot-
|
|
1658
|
-
"starter/docs/governance/agents-routing/engineering-runtime-
|
|
1659
|
-
"starter/docs/governance/agents-routing/doc-only-
|
|
1657
|
+
"starter/docs/governance/ssot-v1.0.md",
|
|
1658
|
+
"starter/docs/governance/agents-routing/engineering-runtime-v1.0.md",
|
|
1659
|
+
"starter/docs/governance/agents-routing/doc-only-v1.0.md",
|
|
1660
1660
|
"profiles/engineering-runtime/profile.md",
|
|
1661
1661
|
"profiles/doc-only/profile.md"
|
|
1662
1662
|
];
|
|
@@ -1738,7 +1738,7 @@ function classifyOwnership(targetPath) {
|
|
|
1738
1738
|
return "shared";
|
|
1739
1739
|
}
|
|
1740
1740
|
function isOtherProfileRouting(targetPath, profile) {
|
|
1741
|
-
return targetPath.startsWith("docs/governance/agents-routing/") && targetPath !== `docs/governance/agents-routing/${profile}-
|
|
1741
|
+
return targetPath.startsWith("docs/governance/agents-routing/") && targetPath !== `docs/governance/agents-routing/${profile}-v1.0.md`;
|
|
1742
1742
|
}
|
|
1743
1743
|
function starterTargetPath(sourcePath) {
|
|
1744
1744
|
if (sourcePath === "starter/AGENTS.template.md") return "AGENTS.md";
|
|
@@ -1800,7 +1800,7 @@ function applyStarterFiles(files, profile) {
|
|
|
1800
1800
|
return 0;
|
|
1801
1801
|
}
|
|
1802
1802
|
function renderAgentsTemplate(template, projectName, profile) {
|
|
1803
|
-
const selectedRoute = `docs/governance/agents-routing/${profile}-
|
|
1803
|
+
const selectedRoute = `docs/governance/agents-routing/${profile}-v1.0.md`;
|
|
1804
1804
|
return template.replace("# PROJECT_NAME AI Router", `# ${projectName} AI Router`).replace("`PROFILE_NAME`", `\`${profile}\``).replace("`PROFILE_ROUTE`", `\`${selectedRoute}\``).replace(/\n{3,}/g, "\n\n");
|
|
1805
1805
|
}
|
|
1806
1806
|
function readFlag(args, flag) {
|
|
@@ -1834,18 +1834,22 @@ function recallLearnings(root, options) {
|
|
|
1834
1834
|
return { query, hits };
|
|
1835
1835
|
}
|
|
1836
1836
|
function loadLearningRecords(root) {
|
|
1837
|
-
const
|
|
1838
|
-
const
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1837
|
+
const recordsByTitle = /* @__PURE__ */ new Map();
|
|
1838
|
+
for (const relativeDir of ["docs/reference/learnings", "docs/solutions"]) {
|
|
1839
|
+
const learningDir = join14(root, relativeDir);
|
|
1840
|
+
if (!existsSync14(learningDir)) continue;
|
|
1841
|
+
for (const path of listMarkdownFiles(learningDir)) {
|
|
1842
|
+
const record = readLearningRecord(root, path);
|
|
1843
|
+
const key = record.title.trim().toLowerCase();
|
|
1844
|
+
if (!recordsByTitle.has(key)) recordsByTitle.set(key, record);
|
|
1842
1845
|
}
|
|
1843
1846
|
}
|
|
1844
1847
|
const conceptsPath = join14(root, "CONCEPTS.md");
|
|
1845
1848
|
if (existsSync14(conceptsPath)) {
|
|
1846
|
-
|
|
1849
|
+
const record = readLearningRecord(root, conceptsPath);
|
|
1850
|
+
recordsByTitle.set(`concepts:${record.title.toLowerCase()}`, record);
|
|
1847
1851
|
}
|
|
1848
|
-
return
|
|
1852
|
+
return [...recordsByTitle.values()];
|
|
1849
1853
|
}
|
|
1850
1854
|
function listMarkdownFiles(dir) {
|
|
1851
1855
|
const files = [];
|
|
@@ -1944,7 +1948,7 @@ function cleanMarkdownLine(input) {
|
|
|
1944
1948
|
|
|
1945
1949
|
// src/learning/capture.ts
|
|
1946
1950
|
import { existsSync as existsSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
1947
|
-
import { join as join15, relative as relative6 } from "node:path";
|
|
1951
|
+
import { basename as basename5, join as join15, relative as relative6 } from "node:path";
|
|
1948
1952
|
function captureLearning(root, options) {
|
|
1949
1953
|
const title = options.title.trim();
|
|
1950
1954
|
const summary = options.summary.trim();
|
|
@@ -1952,10 +1956,11 @@ function captureLearning(root, options) {
|
|
|
1952
1956
|
if (!summary) throw new Error("summary is required");
|
|
1953
1957
|
const category = slugify(options.category ?? "workflow-issues") || "workflow-issues";
|
|
1954
1958
|
const moduleName = options.module?.trim() || "PGS learning capture";
|
|
1955
|
-
const dir = join15(root, "docs/
|
|
1959
|
+
const dir = join15(root, "docs/reference/learnings", category);
|
|
1956
1960
|
mkdirSync5(dir, { recursive: true });
|
|
1957
1961
|
const path = uniquePath(dir, slugify(title) || "learning");
|
|
1958
|
-
|
|
1962
|
+
const idSlug = basename5(path, ".md");
|
|
1963
|
+
writeFileSync4(path, renderLearning({ title, summary, category, moduleName, idSlug }));
|
|
1959
1964
|
return {
|
|
1960
1965
|
relativePath: normalizePath2(relative6(root, path)),
|
|
1961
1966
|
title,
|
|
@@ -1965,12 +1970,23 @@ function captureLearning(root, options) {
|
|
|
1965
1970
|
function renderLearning(options) {
|
|
1966
1971
|
return [
|
|
1967
1972
|
"---",
|
|
1973
|
+
`id: REF-LEARNING-${upperSlug(options.category)}-${upperSlug(options.idSlug)}`,
|
|
1968
1974
|
`title: ${yamlString(options.title)}`,
|
|
1969
|
-
|
|
1975
|
+
"type: reference",
|
|
1976
|
+
"status: stable",
|
|
1977
|
+
"canonical: true",
|
|
1978
|
+
"owner: ai-assisted",
|
|
1979
|
+
`created: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`,
|
|
1980
|
+
`last_reviewed: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`,
|
|
1981
|
+
"domain: learning",
|
|
1982
|
+
"tags:",
|
|
1983
|
+
" - learning-recall",
|
|
1984
|
+
` - ${options.category}`,
|
|
1985
|
+
"pinned: false",
|
|
1986
|
+
"related: []",
|
|
1970
1987
|
`category: ${options.category}`,
|
|
1971
1988
|
`module: ${yamlString(options.moduleName)}`,
|
|
1972
1989
|
"capture_mode: pgs-native",
|
|
1973
|
-
"tags: [learning-recall]",
|
|
1974
1990
|
"---",
|
|
1975
1991
|
"",
|
|
1976
1992
|
`# ${options.title}`,
|
|
@@ -2004,6 +2020,9 @@ function yamlString(input) {
|
|
|
2004
2020
|
function normalizePath2(path) {
|
|
2005
2021
|
return path.split("\\").join("/");
|
|
2006
2022
|
}
|
|
2023
|
+
function upperSlug(input) {
|
|
2024
|
+
return slugify(input).toUpperCase() || "LEARNING";
|
|
2025
|
+
}
|
|
2007
2026
|
|
|
2008
2027
|
// src/commands/learn.ts
|
|
2009
2028
|
function runLearn(args) {
|
|
@@ -2173,7 +2192,7 @@ import { dirname as dirname9 } from "node:path";
|
|
|
2173
2192
|
|
|
2174
2193
|
// src/lens/audit.ts
|
|
2175
2194
|
import { existsSync as existsSync16, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "node:fs";
|
|
2176
|
-
import { basename as
|
|
2195
|
+
import { basename as basename6, dirname as dirname8, join as join16 } from "node:path";
|
|
2177
2196
|
var REQUIRED_ARTIFACTS = [
|
|
2178
2197
|
"manifest.md",
|
|
2179
2198
|
"raw/project-lens/architecture-lens.md",
|
|
@@ -2191,7 +2210,7 @@ function createProjectLensAuditPackage(targetDir, auditDir) {
|
|
|
2191
2210
|
version: 1,
|
|
2192
2211
|
target: {
|
|
2193
2212
|
path: targetDir,
|
|
2194
|
-
name:
|
|
2213
|
+
name: basename6(targetDir) || "target"
|
|
2195
2214
|
},
|
|
2196
2215
|
requiredArtifacts: [...REQUIRED_ARTIFACTS]
|
|
2197
2216
|
};
|
|
@@ -3511,7 +3530,7 @@ import {
|
|
|
3511
3530
|
statSync as statSync4,
|
|
3512
3531
|
writeFileSync as writeFileSync7
|
|
3513
3532
|
} from "node:fs";
|
|
3514
|
-
import { dirname as dirname12, join as join20, relative as relative8, resolve as resolve4 } from "node:path";
|
|
3533
|
+
import { dirname as dirname12, join as join20, relative as relative8, resolve as resolve4, sep } from "node:path";
|
|
3515
3534
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
3516
3535
|
function inspectPortfolioAiHealth(options) {
|
|
3517
3536
|
const endpoints = collectEndpoints(options.manifest);
|
|
@@ -3602,9 +3621,11 @@ function inspectRepository(endpoint, role, secretsRoot, expectedPackageVersion,
|
|
|
3602
3621
|
if (skills.claudeCompatibility === "duplicate-directory") recommendations.push("`.claude/skills` \u662F\u72EC\u7ACB\u526F\u672C\uFF1B\u5EFA\u8BAE\u94FE\u63A5\u5230 `.agents/skills`\uFF0C\u907F\u514D\u53CC\u4EFD\u6280\u80FD\u6F02\u79FB\u3002");
|
|
3603
3622
|
if (skills.claudeCompatibility === "dangling-symlink") recommendations.push("`.claude/skills` \u662F\u65AD\u5F00\u7684\u94FE\u63A5\u3002");
|
|
3604
3623
|
if (hasWorkflowReminderHooks(hooks)) recommendations.push("\u53D1\u73B0 Stop/SubagentStop hook\uFF1B\u786E\u8BA4\u5B83\u662F\u5426\u4ECD\u6709\u9879\u76EE\u4E13\u5C5E\u7528\u9014\uFF0C\u5E76\u79FB\u9664\u9000\u4F11\u7684 PGS \u5DE5\u4F5C\u6D41\u63D0\u9192\u3002");
|
|
3605
|
-
const liveEnv = secrets.repositoryEnvFiles.filter((file) => !file.template);
|
|
3624
|
+
const liveEnv = secrets.repositoryEnvFiles.filter((file) => !file.template && !file.fixture);
|
|
3606
3625
|
if (liveEnv.some((file) => file.tracked)) recommendations.push("\u53D1\u73B0\u88AB Git \u8DDF\u8E2A\u7684\u771F\u5B9E\u73AF\u5883\u6587\u4EF6\uFF1B\u5E94\u7ACB\u5373\u786E\u8BA4\u5176\u4E2D\u662F\u5426\u5305\u542B\u51ED\u636E\u5E76\u8FC1\u51FA\u4ED3\u5E93\u3002");
|
|
3607
|
-
|
|
3626
|
+
if (liveEnv.length > 0 && secrets.centralDirectory === "absent") recommendations.push("\u4ED3\u5E93\u6709\u672C\u5730\u73AF\u5883\u6587\u4EF6\uFF0C\u4F46\u4E2D\u592E `.secrets` \u4E2D\u6CA1\u6709\u5BF9\u5E94\u76EE\u5F55\uFF1B\u786E\u8BA4\u662F\u5426\u9700\u8981\u7EB3\u5165\u5206\u5C42\u7BA1\u7406\u3002");
|
|
3627
|
+
else if (liveEnv.some((file) => !file.centralized)) recommendations.push("\u53D1\u73B0\u771F\u5B9E\u73AF\u5883\u6587\u4EF6\u5C1A\u672A\u8FDE\u63A5\u5230\u672C\u9879\u76EE\u7684\u4E2D\u592E `.secrets` \u76EE\u5F55\uFF1B\u533A\u5206\u53EF\u4E22\u5F03\u751F\u6210\u7269\u4E0E\u672C\u5730\u4E3B\u6765\u6E90\uFF0C\u9700\u4FDD\u7559\u7684\u6765\u6E90\u5E94\u96C6\u4E2D\u540E\u518D\u63A5\u56DE\u9879\u76EE\u3002");
|
|
3628
|
+
if (hasUnsafeCentralSecretPermissions(secrets)) recommendations.push("\u4E2D\u592E\u5BC6\u94A5\u76EE\u5F55\u6216\u6587\u4EF6\u6743\u9650\u8FC7\u5BBD\uFF1B\u76EE\u5F55\u5E94\u4E3A 0700\uFF0C\u914D\u7F6E\u6587\u4EF6\u5E94\u4E3A 0600\u3002");
|
|
3608
3629
|
if (!docs.packages.aligned) recommendations.push(`PGS \u5305\u7248\u672C\u672A\u4E0E\u6267\u884C\u5F15\u64CE ${docs.packages.expected ?? "\u672A\u77E5\u7248\u672C"} \u5BF9\u9F50\uFF1B\u53D1\u5E03\u4E0A\u6E38\u540E\u518D\u540C\u6B65\u76EE\u6807\u4ED3\u5E93\u3002`);
|
|
3609
3630
|
if (role === "target" && !docs.manifest) recommendations.push("\u7F3A\u5C11 docs/governance/MANIFEST.yml\uFF1B\u6587\u6863\u6E05\u5355\u65E0\u6CD5\u8BC1\u660E\u5DF2\u540C\u6B65\u3002");
|
|
3610
3631
|
if (technologyGovernance && !projectModel.projectType) recommendations.push("\u672A\u58F0\u660E\u9879\u76EE\u7C7B\u578B\uFF1B\u65E0\u6CD5\u628A\u5B9E\u9645\u6280\u672F\u4E0E\u4EA7\u54C1\u7EBF\u57FA\u7EBF\u8FDB\u884C\u6BD4\u8F83\u3002");
|
|
@@ -3630,10 +3651,12 @@ function inspectRepository(endpoint, role, secretsRoot, expectedPackageVersion,
|
|
|
3630
3651
|
};
|
|
3631
3652
|
}
|
|
3632
3653
|
function deriveStatus(entries, git, hooks, skills, secrets, projectModel, technologyGovernanceConfigured) {
|
|
3633
|
-
if (!git.isRepository || entries.agents === "missing" || entries.claude === "dangling-symlink" || entries.gemini === "dangling-symlink" || skills.canonical.some((item) => item.kind === "dangling-symlink") || secrets.repositoryEnvFiles.some((file) => file.tracked && !file.template)) return "unhealthy";
|
|
3654
|
+
if (!git.isRepository || entries.agents === "missing" || entries.claude === "dangling-symlink" || entries.gemini === "dangling-symlink" || skills.canonical.some((item) => item.kind === "dangling-symlink") || secrets.repositoryEnvFiles.some((file) => file.tracked && !file.template && !file.fixture) || hasUnsafeCentralSecretPermissions(secrets)) return "unhealthy";
|
|
3634
3655
|
const missingBaseline = projectModel.baseline.some((technology) => !technology.detected && !hasBaselineException(projectModel, technology.id));
|
|
3635
3656
|
const missingSelected = projectModel.optionalCapabilities.some((technology) => technology.selected && !technology.detected);
|
|
3636
|
-
|
|
3657
|
+
const liveEnv = secrets.repositoryEnvFiles.filter((file) => !file.template && !file.fixture);
|
|
3658
|
+
const secretMaterializationNeedsReview = liveEnv.some((file) => !file.centralized);
|
|
3659
|
+
if (entries.agents !== "pgs-router" || entries.claude !== "agents-symlink" || hasWorkflowReminderHooks(hooks) || skills.claudeCompatibility === "duplicate-directory" || skills.claudeCompatibility === "dangling-symlink" || git.branches.length > 1 || git.worktrees.length > 1 || git.dirtyPaths.length > 0 || (git.ahead ?? 0) > 0 || secretMaterializationNeedsReview || technologyGovernanceConfigured && !projectModel.projectType || missingBaseline || missingSelected) return "attention";
|
|
3637
3660
|
return "healthy";
|
|
3638
3661
|
}
|
|
3639
3662
|
function inspectProjectModel(root, endpoint, governance) {
|
|
@@ -3795,11 +3818,14 @@ function inspectClaudeSkillRoot(root) {
|
|
|
3795
3818
|
}
|
|
3796
3819
|
function inspectRepositorySecrets(root, id, secretsRoot, isRepository) {
|
|
3797
3820
|
const centralPath = join20(secretsRoot, id);
|
|
3821
|
+
const centralRealPath = safeRealpath(centralPath);
|
|
3798
3822
|
const envFiles = collectEnvironmentFiles(root).map((path) => ({
|
|
3799
3823
|
path,
|
|
3800
3824
|
tracked: isRepository ? gitTracks(root, path) : false,
|
|
3801
|
-
template:
|
|
3802
|
-
|
|
3825
|
+
template: isEnvironmentTemplate(path),
|
|
3826
|
+
fixture: isEnvironmentFixture(path),
|
|
3827
|
+
symlink: lstatSync6(join20(root, path)).isSymbolicLink(),
|
|
3828
|
+
centralized: pointsInside(join20(root, path), centralRealPath)
|
|
3803
3829
|
}));
|
|
3804
3830
|
return {
|
|
3805
3831
|
centralDirectory: existsSync21(centralPath) ? "present" : "absent",
|
|
@@ -3816,7 +3842,7 @@ function collectEnvironmentFiles(root, current = root, depth = 0) {
|
|
|
3816
3842
|
for (const entry of readdirSync8(current, { withFileTypes: true })) {
|
|
3817
3843
|
if (entry.isDirectory()) {
|
|
3818
3844
|
if (!SKIP_ENV_DIRECTORIES.has(entry.name)) found.push(...collectEnvironmentFiles(root, join20(current, entry.name), depth + 1));
|
|
3819
|
-
} else if (entry.name
|
|
3845
|
+
} else if (isEnvironmentFilename(entry.name) && !isProviderGeneratedEnvironmentFile(entry.name)) {
|
|
3820
3846
|
found.push(relative8(root, join20(current, entry.name)));
|
|
3821
3847
|
}
|
|
3822
3848
|
}
|
|
@@ -3843,6 +3869,35 @@ function basenameOnly(path) {
|
|
|
3843
3869
|
const parts = path.split(/[\\/]/);
|
|
3844
3870
|
return parts[parts.length - 1] ?? path;
|
|
3845
3871
|
}
|
|
3872
|
+
function isEnvironmentFilename(name) {
|
|
3873
|
+
return name === ".env" || name.startsWith(".env.") || name.endsWith(".env");
|
|
3874
|
+
}
|
|
3875
|
+
function isProviderGeneratedEnvironmentFile(name) {
|
|
3876
|
+
return name.endsWith(".pulled");
|
|
3877
|
+
}
|
|
3878
|
+
function isEnvironmentTemplate(path) {
|
|
3879
|
+
return /(^|[._-])(example|sample|template|defaults?)([._-]|$)/i.test(basenameOnly(path));
|
|
3880
|
+
}
|
|
3881
|
+
function isEnvironmentFixture(path) {
|
|
3882
|
+
return /(^|[\\/])(?:tests?|__tests__)[\\/]fixtures?[\\/]/i.test(path) || /(^|[\\/])__fixtures__[\\/]/i.test(path);
|
|
3883
|
+
}
|
|
3884
|
+
function safeRealpath(path) {
|
|
3885
|
+
try {
|
|
3886
|
+
return realpathSync2(path);
|
|
3887
|
+
} catch {
|
|
3888
|
+
return void 0;
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
function pointsInside(path, expectedRoot) {
|
|
3892
|
+
if (!expectedRoot || !lstatSync6(path).isSymbolicLink()) return false;
|
|
3893
|
+
const target = safeRealpath(path);
|
|
3894
|
+
if (!target) return false;
|
|
3895
|
+
const fromRoot = relative8(expectedRoot, target);
|
|
3896
|
+
return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${sep}`);
|
|
3897
|
+
}
|
|
3898
|
+
function hasUnsafeCentralSecretPermissions(secrets) {
|
|
3899
|
+
return secrets.centralDirectory === "present" && (secrets.centralMode !== "700" || secrets.centralFiles.some((file) => file.mode !== "600"));
|
|
3900
|
+
}
|
|
3846
3901
|
function inspectSecretsRoot(path) {
|
|
3847
3902
|
return existsSync21(path) ? { path, exists: true, mode: modeString(statSync4(path).mode) } : { path, exists: false };
|
|
3848
3903
|
}
|
|
@@ -4471,7 +4526,7 @@ function normalizeMarkdownTableCell(cell) {
|
|
|
4471
4526
|
}
|
|
4472
4527
|
function inferInstalledProfile(root) {
|
|
4473
4528
|
const installed = ["engineering-runtime", "doc-only"].filter(
|
|
4474
|
-
(profile) => existsSync23(join22(root, `docs/governance/agents-routing/${profile}-
|
|
4529
|
+
(profile) => existsSync23(join22(root, `docs/governance/agents-routing/${profile}-v1.0.md`))
|
|
4475
4530
|
);
|
|
4476
4531
|
return installed.length === 1 ? installed[0] : void 0;
|
|
4477
4532
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pieai/pro-gov",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
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.
|
|
38
|
+
"@pieai/doc-gov": "^0.5.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@pieai/swimmer-ui-kit": "1.0.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|