pi-evalset-lab 0.1.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/.copier-answers.yml +5 -0
- package/.githooks/pre-commit +12 -0
- package/.github/CODEOWNERS +12 -0
- package/.github/ISSUE_TEMPLATE/bug-report.yml +63 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/docs.yml +39 -0
- package/.github/ISSUE_TEMPLATE/feature-request.yml +41 -0
- package/.github/VOUCHED.td +8 -0
- package/.github/dependabot.yml +13 -0
- package/.github/pull_request_template.md +34 -0
- package/.github/workflows/ci.yml +37 -0
- package/.github/workflows/publish.yml +60 -0
- package/.github/workflows/release-please.yml +25 -0
- package/.github/workflows/vouch-check-pr.yml +29 -0
- package/.github/workflows/vouch-manage.yml +34 -0
- package/.pi/extensions/startup-intake-router.ts +151 -0
- package/.pi/prompts/init-project-docs.md +32 -0
- package/.release-please-config.json +11 -0
- package/.release-please-manifest.json +3 -0
- package/AGENTS.md +39 -0
- package/CHANGELOG.md +43 -0
- package/CODE_OF_CONDUCT.md +50 -0
- package/CONTRIBUTING.md +28 -0
- package/NEXT_SESSION_PROMPT.md +14 -0
- package/README.md +246 -0
- package/SECURITY.md +34 -0
- package/SUPPORT.md +37 -0
- package/docs/dev/CONTRIBUTING.md +37 -0
- package/docs/dev/EXTENSION_SOP.md +43 -0
- package/docs/dev/next_steps.md +17 -0
- package/docs/dev/plans/001-initial-plan.md +24 -0
- package/docs/dev/status.md +21 -0
- package/docs/org/operating_model.md +39 -0
- package/docs/org/project-docs-intake.questions.json +60 -0
- package/docs/project/foundation.md +28 -0
- package/docs/project/incentives.md +17 -0
- package/docs/project/resources.md +26 -0
- package/docs/project/skills.md +17 -0
- package/docs/project/strategic_goals.md +18 -0
- package/docs/project/tactical_goals.md +39 -0
- package/docs/project/vision.md +21 -0
- package/examples/.gitkeep +0 -0
- package/examples/fixed-task-set-v2.json +127 -0
- package/examples/fixed-task-set-v3.json +126 -0
- package/examples/fixed-task-set.json +22 -0
- package/examples/system-baseline.txt +1 -0
- package/examples/system-candidate.txt +6 -0
- package/extensions/evalset.ts +1090 -0
- package/external/.gitkeep +0 -0
- package/ontology/.gitkeep +0 -0
- package/package.json +31 -0
- package/policy/security-policy.json +10 -0
- package/prek.toml +15 -0
- package/prompts/implementation-planning.md +17 -0
- package/prompts/init-project-docs.md +32 -0
- package/prompts/security-review.md +17 -0
- package/scripts/docs-list.sh +50 -0
- package/scripts/init-project-docs.sh +56 -0
- package/scripts/install-hooks.sh +13 -0
- package/scripts/sync-to-live.sh +91 -0
- package/scripts/validate-structure.sh +325 -0
- package/src/.gitkeep +0 -0
- package/tests/.gitkeep +0 -0
|
File without changes
|
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-evalset-lab",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "pi extension package: pi-evalset-lab",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": ["pi-package"],
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/tryingET/pi-evalset-lab.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/tryingET/pi-evalset-lab/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/tryingET/pi-evalset-lab#readme",
|
|
16
|
+
"scripts": {
|
|
17
|
+
"check": "bash ./scripts/validate-structure.sh",
|
|
18
|
+
"test": "bash ./scripts/validate-structure.sh",
|
|
19
|
+
"docs:list": "bash ./scripts/docs-list.sh",
|
|
20
|
+
"docs:list:workspace": "bash ./scripts/docs-list.sh --workspace --discover",
|
|
21
|
+
"docs:list:json": "bash ./scripts/docs-list.sh --json"
|
|
22
|
+
},
|
|
23
|
+
"pi": {
|
|
24
|
+
"extensions": ["./extensions/evalset.ts"],
|
|
25
|
+
"prompts": ["./prompts"]
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@mariozechner/pi-coding-agent": "*",
|
|
29
|
+
"@mariozechner/pi-ai": "*"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/prek.toml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
minimum_prek_version = "0.3.0"
|
|
2
|
+
|
|
3
|
+
[[repos]]
|
|
4
|
+
repo = "local"
|
|
5
|
+
hooks = [
|
|
6
|
+
{
|
|
7
|
+
id = "validate-structure",
|
|
8
|
+
name = "validate structure",
|
|
9
|
+
language = "system",
|
|
10
|
+
entry = "bash ./scripts/validate-structure.sh",
|
|
11
|
+
pass_filenames = false,
|
|
12
|
+
always_run = true,
|
|
13
|
+
stages = ["pre-commit"]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Draft an implementation plan for a requested change
|
|
3
|
+
system4d:
|
|
4
|
+
container: "Prompt template for implementation planning."
|
|
5
|
+
compass: "Turn requests into actionable, risk-aware plans."
|
|
6
|
+
engine: "Scope -> tasks -> validation -> rollout."
|
|
7
|
+
fog: "Hidden constraints unless assumptions are surfaced."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Create an implementation plan for this request: $@
|
|
11
|
+
|
|
12
|
+
Include:
|
|
13
|
+
- Scope and non-goals
|
|
14
|
+
- Key risks and mitigations
|
|
15
|
+
- Step-by-step implementation tasks
|
|
16
|
+
- Validation commands and expected outcomes
|
|
17
|
+
- Rollout and rollback notes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run interview-first initialization for organization and project docs
|
|
3
|
+
system4d:
|
|
4
|
+
container: "Prompt template for document initialization workflow."
|
|
5
|
+
compass: "Create compact, aligned org/project docs from structured intake."
|
|
6
|
+
engine: "Intent -> interview -> synthesize -> update docs -> verify."
|
|
7
|
+
fog: "Incomplete intake answers can cause ambiguous documentation."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Initialize organization and project docs from interactive intake.
|
|
11
|
+
|
|
12
|
+
Startup intent (if provided): $@
|
|
13
|
+
|
|
14
|
+
Steps:
|
|
15
|
+
1. Read `docs/org/project-docs-intake.questions.json`.
|
|
16
|
+
2. If startup intent is non-empty, create `docs/org/project-docs-intake.runtime.questions.json` with one prepended question:
|
|
17
|
+
- `id`: `startup_intent_confirmation`
|
|
18
|
+
- `type`: `text`
|
|
19
|
+
- `question`: `Startup intent captured: <startup intent>. Confirm or refine this intent before continuing.`
|
|
20
|
+
3. Run the `interview` tool:
|
|
21
|
+
- `questions`: runtime file from step 2 if created, otherwise `docs/org/project-docs-intake.questions.json`
|
|
22
|
+
- `timeout`: `900`
|
|
23
|
+
4. Use interview responses to update these files:
|
|
24
|
+
- `docs/org/operating_model.md`
|
|
25
|
+
- `docs/project/foundation.md`
|
|
26
|
+
- `docs/project/vision.md`
|
|
27
|
+
- `docs/project/strategic_goals.md`
|
|
28
|
+
- `docs/project/tactical_goals.md`
|
|
29
|
+
5. Keep wording fully in English.
|
|
30
|
+
6. Keep **organization purpose** separate from **project purpose**.
|
|
31
|
+
7. Keep output compact.
|
|
32
|
+
8. Run `bash ./scripts/validate-structure.sh`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review a change for security risks and mitigations
|
|
3
|
+
system4d:
|
|
4
|
+
container: "Prompt template for security-focused review."
|
|
5
|
+
compass: "Identify practical vulnerabilities before release."
|
|
6
|
+
engine: "Threats -> impact -> mitigations -> verification."
|
|
7
|
+
fog: "Partial context can hide exploit paths."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Review this change for security concerns: $@
|
|
11
|
+
|
|
12
|
+
Focus on:
|
|
13
|
+
- Input validation and injection risk
|
|
14
|
+
- Privilege boundaries and secret handling
|
|
15
|
+
- Dependency and supply-chain risk
|
|
16
|
+
- Safe failure modes and logging
|
|
17
|
+
- Concrete remediations with priority
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
DEFAULT_SCRIPT="$HOME/ai-society/core/agent-scripts/scripts/docs-list.mjs"
|
|
6
|
+
LOCAL_FALLBACK_SCRIPT="$ROOT_DIR/scripts/docs-list.mjs"
|
|
7
|
+
|
|
8
|
+
usage() {
|
|
9
|
+
cat <<'USAGE'
|
|
10
|
+
Usage: ./scripts/docs-list.sh [docs-list args]
|
|
11
|
+
|
|
12
|
+
Resolves docs-list script in this order:
|
|
13
|
+
1) DOCS_LIST_SCRIPT env var (absolute/relative path)
|
|
14
|
+
2) Local fallback: ./scripts/docs-list.mjs
|
|
15
|
+
3) Default global path: ~/ai-society/core/agent-scripts/scripts/docs-list.mjs
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
./scripts/docs-list.sh
|
|
19
|
+
./scripts/docs-list.sh --workspace --discover
|
|
20
|
+
./scripts/docs-list.sh --json
|
|
21
|
+
USAGE
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
25
|
+
usage
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
if ! command -v node >/dev/null 2>&1; then
|
|
30
|
+
echo "Error: node is required to run docs-list." >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
SCRIPT_PATH=""
|
|
35
|
+
|
|
36
|
+
if [[ -n "${DOCS_LIST_SCRIPT:-}" ]]; then
|
|
37
|
+
SCRIPT_PATH="${DOCS_LIST_SCRIPT}"
|
|
38
|
+
elif [[ -f "$LOCAL_FALLBACK_SCRIPT" ]]; then
|
|
39
|
+
SCRIPT_PATH="$LOCAL_FALLBACK_SCRIPT"
|
|
40
|
+
else
|
|
41
|
+
SCRIPT_PATH="$DEFAULT_SCRIPT"
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if [[ ! -f "$SCRIPT_PATH" ]]; then
|
|
45
|
+
echo "Error: docs-list script not found: $SCRIPT_PATH" >&2
|
|
46
|
+
echo "Set DOCS_LIST_SCRIPT to your docs-list.mjs path, or install agent-scripts at: $DEFAULT_SCRIPT" >&2
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
node "$SCRIPT_PATH" "$@"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
QUESTIONS_FILE="$ROOT_DIR/docs/org/project-docs-intake.questions.json"
|
|
6
|
+
ROUTER_FILE="$ROOT_DIR/.pi/extensions/startup-intake-router.ts"
|
|
7
|
+
PROMPT_FILE="$ROOT_DIR/.pi/prompts/init-project-docs.md"
|
|
8
|
+
|
|
9
|
+
INSTALL_INTERVIEW=false
|
|
10
|
+
|
|
11
|
+
while [[ $# -gt 0 ]]; do
|
|
12
|
+
case "$1" in
|
|
13
|
+
--install-interview)
|
|
14
|
+
INSTALL_INTERVIEW=true
|
|
15
|
+
;;
|
|
16
|
+
-h|--help)
|
|
17
|
+
echo "Usage: ./scripts/init-project-docs.sh [--install-interview]"
|
|
18
|
+
exit 0
|
|
19
|
+
;;
|
|
20
|
+
*)
|
|
21
|
+
echo "Unknown arg: $1" >&2
|
|
22
|
+
echo "Usage: ./scripts/init-project-docs.sh [--install-interview]" >&2
|
|
23
|
+
exit 1
|
|
24
|
+
;;
|
|
25
|
+
esac
|
|
26
|
+
shift
|
|
27
|
+
done
|
|
28
|
+
|
|
29
|
+
for required in "$QUESTIONS_FILE" "$ROUTER_FILE" "$PROMPT_FILE"; do
|
|
30
|
+
if [[ ! -f "$required" ]]; then
|
|
31
|
+
echo "Missing required file: $required" >&2
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
if [[ "$INSTALL_INTERVIEW" == "true" ]]; then
|
|
37
|
+
if command -v pi-interview >/dev/null 2>&1; then
|
|
38
|
+
pi-interview
|
|
39
|
+
else
|
|
40
|
+
echo "pi-interview command not found. Install the interactive-interview extension first, then rerun with --install-interview." >&2
|
|
41
|
+
fi
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
echo "Interview-first document setup"
|
|
45
|
+
echo ""
|
|
46
|
+
echo "0) Optional: run npm run docs:list to review docs + read_when hints."
|
|
47
|
+
echo "1) Ensure the interview extension is installed and loaded in pi."
|
|
48
|
+
echo "2) Open this repository in pi."
|
|
49
|
+
echo "3) Send a natural-language intent as the first non-command message in a session."
|
|
50
|
+
echo "4) Router will prefill: /init-project-docs \"<intent>\""
|
|
51
|
+
echo "5) Review/edit and run that command."
|
|
52
|
+
echo ""
|
|
53
|
+
echo "Fallback: run /init-project-docs manually."
|
|
54
|
+
echo "Questions source: $QUESTIONS_FILE"
|
|
55
|
+
echo ""
|
|
56
|
+
echo "After updates, run: bash ./scripts/validate-structure.sh"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
|
|
6
|
+
git -C "$ROOT_DIR" config core.hooksPath .githooks
|
|
7
|
+
echo "Configured git hooks path: .githooks"
|
|
8
|
+
|
|
9
|
+
if command -v prek >/dev/null 2>&1; then
|
|
10
|
+
echo "prek detected: pre-commit hook will run prek.toml"
|
|
11
|
+
else
|
|
12
|
+
echo "prek not found: pre-commit hook will fallback to scripts/validate-structure.sh"
|
|
13
|
+
fi
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
WITH_POLICY=false
|
|
5
|
+
WITH_PROMPTS=false
|
|
6
|
+
|
|
7
|
+
usage() {
|
|
8
|
+
cat <<'USAGE'
|
|
9
|
+
Usage: ./scripts/sync-to-live.sh [--with-policy] [--with-prompts] [--all]
|
|
10
|
+
|
|
11
|
+
Copies all package extension entrypoints from ./extensions into ~/.pi/agent/extensions/.
|
|
12
|
+
Optional flags also sync policy and prompt templates.
|
|
13
|
+
USAGE
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
while [[ $# -gt 0 ]]; do
|
|
17
|
+
case "$1" in
|
|
18
|
+
--with-policy)
|
|
19
|
+
WITH_POLICY=true
|
|
20
|
+
;;
|
|
21
|
+
--with-prompts)
|
|
22
|
+
WITH_PROMPTS=true
|
|
23
|
+
;;
|
|
24
|
+
--all)
|
|
25
|
+
WITH_POLICY=true
|
|
26
|
+
WITH_PROMPTS=true
|
|
27
|
+
;;
|
|
28
|
+
-h|--help)
|
|
29
|
+
usage
|
|
30
|
+
exit 0
|
|
31
|
+
;;
|
|
32
|
+
*)
|
|
33
|
+
echo "Unknown arg: $1" >&2
|
|
34
|
+
usage
|
|
35
|
+
exit 1
|
|
36
|
+
;;
|
|
37
|
+
esac
|
|
38
|
+
shift
|
|
39
|
+
done
|
|
40
|
+
|
|
41
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
42
|
+
SOURCE_DIR="$ROOT_DIR/extensions"
|
|
43
|
+
TARGET_DIR="$HOME/.pi/agent/extensions"
|
|
44
|
+
|
|
45
|
+
mkdir -p "$TARGET_DIR"
|
|
46
|
+
|
|
47
|
+
shopt -s nullglob
|
|
48
|
+
extension_files=("$SOURCE_DIR"/*.ts)
|
|
49
|
+
if (( ${#extension_files[@]} == 0 )); then
|
|
50
|
+
echo "No extension files found in: $SOURCE_DIR" >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
for source_file in "${extension_files[@]}"; do
|
|
55
|
+
target_file="$TARGET_DIR/$(basename "$source_file")"
|
|
56
|
+
cp "$source_file" "$target_file"
|
|
57
|
+
echo "Synced extension: $source_file -> $target_file"
|
|
58
|
+
done
|
|
59
|
+
shopt -u nullglob
|
|
60
|
+
|
|
61
|
+
if [[ "$WITH_PROMPTS" == "true" ]]; then
|
|
62
|
+
PROMPT_SOURCE_DIR="$ROOT_DIR/prompts"
|
|
63
|
+
PROMPT_TARGET_DIR="$HOME/.pi/agent/prompts"
|
|
64
|
+
mkdir -p "$PROMPT_TARGET_DIR"
|
|
65
|
+
|
|
66
|
+
shopt -s nullglob
|
|
67
|
+
prompt_files=("$PROMPT_SOURCE_DIR"/*.md)
|
|
68
|
+
if (( ${#prompt_files[@]} == 0 )); then
|
|
69
|
+
echo "No prompt templates found in: $PROMPT_SOURCE_DIR"
|
|
70
|
+
else
|
|
71
|
+
for prompt_file in "${prompt_files[@]}"; do
|
|
72
|
+
cp "$prompt_file" "$PROMPT_TARGET_DIR/"
|
|
73
|
+
echo "Synced prompt: $prompt_file -> $PROMPT_TARGET_DIR/$(basename "$prompt_file")"
|
|
74
|
+
done
|
|
75
|
+
fi
|
|
76
|
+
shopt -u nullglob
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
if [[ "$WITH_POLICY" == "true" ]]; then
|
|
80
|
+
POLICY_SOURCE="$ROOT_DIR/policy/security-policy.json"
|
|
81
|
+
POLICY_TARGET="$HOME/.pi/agent/security-policy.json"
|
|
82
|
+
|
|
83
|
+
if [[ -f "$POLICY_SOURCE" ]]; then
|
|
84
|
+
cp "$POLICY_SOURCE" "$POLICY_TARGET"
|
|
85
|
+
echo "Synced policy: $POLICY_SOURCE -> $POLICY_TARGET"
|
|
86
|
+
else
|
|
87
|
+
echo "Policy file not found: $POLICY_SOURCE (skipped)"
|
|
88
|
+
fi
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
echo "Done. In pi, run /reload to pick up changes."
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
cd "$ROOT_DIR"
|
|
6
|
+
|
|
7
|
+
required_files=(
|
|
8
|
+
"README.md"
|
|
9
|
+
"CHANGELOG.md"
|
|
10
|
+
"SECURITY.md"
|
|
11
|
+
"CODE_OF_CONDUCT.md"
|
|
12
|
+
"SUPPORT.md"
|
|
13
|
+
"CONTRIBUTING.md"
|
|
14
|
+
"AGENTS.md"
|
|
15
|
+
".copier-answers.yml"
|
|
16
|
+
"prek.toml"
|
|
17
|
+
".github/CODEOWNERS"
|
|
18
|
+
".github/dependabot.yml"
|
|
19
|
+
".github/pull_request_template.md"
|
|
20
|
+
".github/VOUCHED.td"
|
|
21
|
+
".github/ISSUE_TEMPLATE/bug-report.yml"
|
|
22
|
+
".github/ISSUE_TEMPLATE/feature-request.yml"
|
|
23
|
+
".github/ISSUE_TEMPLATE/docs.yml"
|
|
24
|
+
".github/ISSUE_TEMPLATE/config.yml"
|
|
25
|
+
".github/workflows/ci.yml"
|
|
26
|
+
".github/workflows/release-please.yml"
|
|
27
|
+
".github/workflows/publish.yml"
|
|
28
|
+
".github/workflows/vouch-check-pr.yml"
|
|
29
|
+
".github/workflows/vouch-manage.yml"
|
|
30
|
+
".release-please-config.json"
|
|
31
|
+
".release-please-manifest.json"
|
|
32
|
+
"docs/org/operating_model.md"
|
|
33
|
+
"docs/org/project-docs-intake.questions.json"
|
|
34
|
+
"docs/project/foundation.md"
|
|
35
|
+
"docs/project/vision.md"
|
|
36
|
+
"docs/project/incentives.md"
|
|
37
|
+
"docs/project/resources.md"
|
|
38
|
+
"docs/project/skills.md"
|
|
39
|
+
"docs/project/strategic_goals.md"
|
|
40
|
+
"docs/project/tactical_goals.md"
|
|
41
|
+
"docs/dev/next_steps.md"
|
|
42
|
+
"docs/dev/status.md"
|
|
43
|
+
"docs/dev/CONTRIBUTING.md"
|
|
44
|
+
"docs/dev/EXTENSION_SOP.md"
|
|
45
|
+
".pi/extensions/startup-intake-router.ts"
|
|
46
|
+
".pi/prompts/init-project-docs.md"
|
|
47
|
+
"scripts/sync-to-live.sh"
|
|
48
|
+
"scripts/install-hooks.sh"
|
|
49
|
+
"scripts/init-project-docs.sh"
|
|
50
|
+
"scripts/docs-list.sh"
|
|
51
|
+
"scripts/validate-structure.sh"
|
|
52
|
+
".githooks/pre-commit"
|
|
53
|
+
"prompts/implementation-planning.md"
|
|
54
|
+
"prompts/security-review.md"
|
|
55
|
+
"prompts/init-project-docs.md"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
required_dirs=(
|
|
59
|
+
".github"
|
|
60
|
+
".github/workflows"
|
|
61
|
+
".github/ISSUE_TEMPLATE"
|
|
62
|
+
"docs/org"
|
|
63
|
+
"docs/dev/plans"
|
|
64
|
+
"examples"
|
|
65
|
+
"external"
|
|
66
|
+
"ontology"
|
|
67
|
+
"policy"
|
|
68
|
+
"scripts"
|
|
69
|
+
"src"
|
|
70
|
+
"tests"
|
|
71
|
+
".pi"
|
|
72
|
+
".pi/extensions"
|
|
73
|
+
".pi/prompts"
|
|
74
|
+
".githooks"
|
|
75
|
+
"prompts"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
required_executables=(
|
|
79
|
+
"scripts/sync-to-live.sh"
|
|
80
|
+
"scripts/install-hooks.sh"
|
|
81
|
+
"scripts/init-project-docs.sh"
|
|
82
|
+
"scripts/docs-list.sh"
|
|
83
|
+
"scripts/validate-structure.sh"
|
|
84
|
+
".githooks/pre-commit"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
errors=0
|
|
88
|
+
|
|
89
|
+
for required_file in "${required_files[@]}"; do
|
|
90
|
+
if [[ ! -f "$required_file" ]]; then
|
|
91
|
+
echo "Missing required file: $required_file" >&2
|
|
92
|
+
((errors+=1))
|
|
93
|
+
fi
|
|
94
|
+
done
|
|
95
|
+
|
|
96
|
+
for required_dir in "${required_dirs[@]}"; do
|
|
97
|
+
if [[ ! -d "$required_dir" ]]; then
|
|
98
|
+
echo "Missing required directory: $required_dir" >&2
|
|
99
|
+
((errors+=1))
|
|
100
|
+
fi
|
|
101
|
+
done
|
|
102
|
+
|
|
103
|
+
for executable in "${required_executables[@]}"; do
|
|
104
|
+
if [[ ! -x "$executable" ]]; then
|
|
105
|
+
echo "Expected executable bit on: $executable" >&2
|
|
106
|
+
((errors+=1))
|
|
107
|
+
fi
|
|
108
|
+
done
|
|
109
|
+
|
|
110
|
+
plan_count=$(find "docs/dev/plans" -maxdepth 1 -type f -name "*.md" | wc -l | tr -d ' ')
|
|
111
|
+
if [[ "$plan_count" -lt 1 ]]; then
|
|
112
|
+
echo "docs/dev/plans must contain at least one markdown plan file" >&2
|
|
113
|
+
((errors+=1))
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
for copier_key in "_src_path:" "repo_name:" "command_name:"; do
|
|
117
|
+
if ! grep -q "^${copier_key}" ".copier-answers.yml"; then
|
|
118
|
+
echo "Missing copier answer key in .copier-answers.yml: ${copier_key}" >&2
|
|
119
|
+
((errors+=1))
|
|
120
|
+
fi
|
|
121
|
+
done
|
|
122
|
+
|
|
123
|
+
placeholder_pattern='\{username\}|\{repo\}|\{discordInvite\}|\{@twitter\}'
|
|
124
|
+
placeholder_hits="$(grep -R -nE "$placeholder_pattern" .github || true)"
|
|
125
|
+
if [[ -n "$placeholder_hits" ]]; then
|
|
126
|
+
echo "Unresolved placeholders found under .github:" >&2
|
|
127
|
+
echo "$placeholder_hits" >&2
|
|
128
|
+
((errors+=1))
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
vouch_ref="0e11a71bba23218a284d3ecca162e75a110fd7e3"
|
|
132
|
+
if ! grep -q "mitchellh/vouch/action/check-pr@${vouch_ref}" ".github/workflows/vouch-check-pr.yml"; then
|
|
133
|
+
echo "vouch-check-pr workflow must pin mitchellh/vouch/action/check-pr to ${vouch_ref}" >&2
|
|
134
|
+
((errors+=1))
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
if ! grep -q "mitchellh/vouch/action/manage-by-issue@${vouch_ref}" ".github/workflows/vouch-manage.yml"; then
|
|
138
|
+
echo "vouch-manage workflow must pin mitchellh/vouch/action/manage-by-issue to ${vouch_ref}" >&2
|
|
139
|
+
((errors+=1))
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
if grep -n "@main" .github/workflows/vouch-*.yml >/dev/null 2>&1; then
|
|
143
|
+
echo "vouch workflows must not use @main refs" >&2
|
|
144
|
+
((errors+=1))
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
if ! grep -q "pull_request_target" ".github/workflows/vouch-check-pr.yml"; then
|
|
148
|
+
echo "vouch-check-pr workflow must trigger on pull_request_target" >&2
|
|
149
|
+
((errors+=1))
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
if ! grep -q "require-vouch" ".github/workflows/vouch-check-pr.yml"; then
|
|
153
|
+
echo "vouch-check-pr workflow must set require-vouch" >&2
|
|
154
|
+
((errors+=1))
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
if ! grep -q "auto-close" ".github/workflows/vouch-check-pr.yml"; then
|
|
158
|
+
echo "vouch-check-pr workflow must set auto-close" >&2
|
|
159
|
+
((errors+=1))
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
if ! grep -q "issue_comment" ".github/workflows/vouch-manage.yml"; then
|
|
163
|
+
echo "vouch-manage workflow must trigger on issue_comment" >&2
|
|
164
|
+
((errors+=1))
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
if ! grep -q "concurrency:" ".github/workflows/vouch-manage.yml" || ! grep -q "group: vouch-manage" ".github/workflows/vouch-manage.yml"; then
|
|
168
|
+
echo "vouch-manage workflow must define serialized concurrency" >&2
|
|
169
|
+
((errors+=1))
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
if ! grep -q "vouched-file: .github/VOUCHED.td" ".github/workflows/vouch-manage.yml"; then
|
|
173
|
+
echo "vouch-manage workflow must target .github/VOUCHED.td" >&2
|
|
174
|
+
((errors+=1))
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
if grep -q "@your-github-handle" ".github/CODEOWNERS"; then
|
|
178
|
+
echo ".github/CODEOWNERS must not keep @your-github-handle placeholder" >&2
|
|
179
|
+
((errors+=1))
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
if ! grep -Eq "^github:[A-Za-z0-9][A-Za-z0-9-]*" ".github/VOUCHED.td"; then
|
|
183
|
+
echo ".github/VOUCHED.td must include at least one github maintainer entry" >&2
|
|
184
|
+
((errors+=1))
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
if command -v node >/dev/null 2>&1; then
|
|
188
|
+
if ! node - <<'NODE'
|
|
189
|
+
const fs = require("node:fs");
|
|
190
|
+
|
|
191
|
+
let failed = false;
|
|
192
|
+
const fail = (msg) => {
|
|
193
|
+
console.error(msg);
|
|
194
|
+
failed = true;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
const qPath = "docs/org/project-docs-intake.questions.json";
|
|
199
|
+
const q = JSON.parse(fs.readFileSync(qPath, "utf8"));
|
|
200
|
+
if (!q.title || !Array.isArray(q.questions) || q.questions.length === 0) {
|
|
201
|
+
fail(`Invalid interview questions file: ${qPath}`);
|
|
202
|
+
}
|
|
203
|
+
} catch (error) {
|
|
204
|
+
fail(`Failed to parse interview questions file: ${error.message}`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
const p = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
|
209
|
+
if (!Array.isArray(p.keywords) || !p.keywords.includes("pi-package")) {
|
|
210
|
+
fail("package.json missing keywords entry: pi-package");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const ext = p.pi?.extensions;
|
|
214
|
+
if (!Array.isArray(ext) || ext.length < 1) {
|
|
215
|
+
fail("package.json missing pi.extensions array");
|
|
216
|
+
} else {
|
|
217
|
+
for (const entry of ext) {
|
|
218
|
+
const normalized = entry.replace(/^\.\//, "");
|
|
219
|
+
if (!fs.existsSync(normalized)) {
|
|
220
|
+
fail(`pi.extensions entry does not exist: ${entry}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const prompts = p.pi?.prompts;
|
|
226
|
+
if (!Array.isArray(prompts) || prompts.length < 1) {
|
|
227
|
+
fail("package.json missing pi.prompts array");
|
|
228
|
+
} else {
|
|
229
|
+
for (const entry of prompts) {
|
|
230
|
+
const normalized = entry.replace(/\/$/, "").replace(/^\.\//, "");
|
|
231
|
+
if (!fs.existsSync(normalized)) {
|
|
232
|
+
fail(`pi.prompts entry does not exist: ${entry}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const checkScript = p.scripts?.check;
|
|
238
|
+
if (checkScript !== "bash ./scripts/validate-structure.sh") {
|
|
239
|
+
fail("package.json scripts.check must be 'bash ./scripts/validate-structure.sh'");
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const testScript = p.scripts?.test;
|
|
243
|
+
if (testScript !== "bash ./scripts/validate-structure.sh") {
|
|
244
|
+
fail("package.json scripts.test must be 'bash ./scripts/validate-structure.sh'");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const docsListScript = p.scripts?.["docs:list"];
|
|
248
|
+
if (docsListScript !== "bash ./scripts/docs-list.sh") {
|
|
249
|
+
fail("package.json scripts.docs:list must be 'bash ./scripts/docs-list.sh'");
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const docsListWorkspaceScript = p.scripts?.["docs:list:workspace"];
|
|
253
|
+
if (docsListWorkspaceScript !== "bash ./scripts/docs-list.sh --workspace --discover") {
|
|
254
|
+
fail("package.json scripts.docs:list:workspace must be 'bash ./scripts/docs-list.sh --workspace --discover'");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const docsListJsonScript = p.scripts?.["docs:list:json"];
|
|
258
|
+
if (docsListJsonScript !== "bash ./scripts/docs-list.sh --json") {
|
|
259
|
+
fail("package.json scripts.docs:list:json must be 'bash ./scripts/docs-list.sh --json'");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const rpConfig = JSON.parse(fs.readFileSync(".release-please-config.json", "utf8"));
|
|
263
|
+
if (rpConfig["include-v-in-tag"] !== true) {
|
|
264
|
+
fail(".release-please-config.json must set include-v-in-tag=true");
|
|
265
|
+
}
|
|
266
|
+
if (!rpConfig.packages || !rpConfig.packages["."]) {
|
|
267
|
+
fail(".release-please-config.json must include packages['.']");
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const rpManifest = JSON.parse(fs.readFileSync(".release-please-manifest.json", "utf8"));
|
|
271
|
+
if (!rpManifest["."]) {
|
|
272
|
+
fail(".release-please-manifest.json must include '.' version entry");
|
|
273
|
+
}
|
|
274
|
+
const versionPattern = /^\d+\.\d+\.\d+([-.][0-9A-Za-z.]+)?$/;
|
|
275
|
+
if (!versionPattern.test(rpManifest["."])) {
|
|
276
|
+
fail(".release-please-manifest.json '.' entry must match X.Y.Z");
|
|
277
|
+
}
|
|
278
|
+
if (rpManifest["."] !== p.version) {
|
|
279
|
+
fail(".release-please-manifest.json '.' entry must match package.json version");
|
|
280
|
+
}
|
|
281
|
+
} catch (error) {
|
|
282
|
+
fail(`Failed to validate package/release metadata: ${error.message}`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
process.exit(failed ? 1 : 0);
|
|
286
|
+
NODE
|
|
287
|
+
then
|
|
288
|
+
((errors+=1))
|
|
289
|
+
fi
|
|
290
|
+
fi
|
|
291
|
+
|
|
292
|
+
while IFS= read -r -d '' markdown_file; do
|
|
293
|
+
if [[ "$(head -n 1 "$markdown_file")" != "---" ]]; then
|
|
294
|
+
echo "Missing YAML frontmatter start in: $markdown_file" >&2
|
|
295
|
+
((errors+=1))
|
|
296
|
+
continue
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
if ! grep -q "^system4d:" "$markdown_file"; then
|
|
300
|
+
echo "Missing system4d section in: $markdown_file" >&2
|
|
301
|
+
((errors+=1))
|
|
302
|
+
continue
|
|
303
|
+
fi
|
|
304
|
+
|
|
305
|
+
for key in container compass engine fog; do
|
|
306
|
+
if ! grep -q "^ $key:" "$markdown_file"; then
|
|
307
|
+
echo "Missing system4d.$key in: $markdown_file" >&2
|
|
308
|
+
((errors+=1))
|
|
309
|
+
fi
|
|
310
|
+
done
|
|
311
|
+
|
|
312
|
+
if [[ "$markdown_file" == "./prompts/"* || "$markdown_file" == "./.pi/prompts/"* ]]; then
|
|
313
|
+
if ! grep -q "^description:" "$markdown_file"; then
|
|
314
|
+
echo "Prompt template missing frontmatter description: $markdown_file" >&2
|
|
315
|
+
((errors+=1))
|
|
316
|
+
fi
|
|
317
|
+
fi
|
|
318
|
+
done < <(find . -type f -name "*.md" ! -path "./.git/*" ! -path "./node_modules/*" -print0)
|
|
319
|
+
|
|
320
|
+
if [[ "$errors" -gt 0 ]]; then
|
|
321
|
+
echo "Structure validation failed with $errors issue(s)." >&2
|
|
322
|
+
exit 1
|
|
323
|
+
fi
|
|
324
|
+
|
|
325
|
+
echo "Structure validation passed."
|
package/src/.gitkeep
ADDED
|
File without changes
|
package/tests/.gitkeep
ADDED
|
File without changes
|