@svayam-opensource/prj 0.5.1
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/LICENSE +21 -0
- package/README.md +123 -0
- package/agent/harness-manifest.yaml +225 -0
- package/agent/session-protocol.md +116 -0
- package/bin/prj +21 -0
- package/package.json +41 -0
- package/prj +2381 -0
- package/scripts/add-repo.sh +126 -0
- package/scripts/cancel.sh +157 -0
- package/scripts/close-knowledge.sh +250 -0
- package/scripts/close-project.sh +233 -0
- package/scripts/create-task.sh +226 -0
- package/scripts/install-deps.sh +292 -0
- package/scripts/join.sh +89 -0
- package/scripts/lib.sh +841 -0
- package/scripts/merge-task.sh +163 -0
- package/scripts/onboard-repo.sh +275 -0
- package/scripts/pause.sh +80 -0
- package/scripts/project-access.sh +34 -0
- package/scripts/propose-knowledge.sh +168 -0
- package/scripts/release-to-public.sh +185 -0
- package/scripts/render-harness.sh +151 -0
- package/scripts/resume.sh +103 -0
- package/scripts/seed.sh +774 -0
- package/scripts/sync-from-publish.sh +193 -0
- package/scripts/sync.sh +90 -0
- package/scripts/test-merge.sh +100 -0
- package/scripts/validate/check_knowledge.py +158 -0
- package/scripts/validate/check_privacy.py +211 -0
- package/scripts/validate/check_protocol.py +117 -0
- package/scripts/validate/check_secrets.py +175 -0
- package/scripts/validate/run.py +391 -0
- package/setup.sh +529 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Script: merge-task
|
|
3
|
+
# Purpose: Merges a completed sub-branch back into the project integration branch.
|
|
4
|
+
# Archives sub-branch. Closes the GitHub Issue(s) it covers.
|
|
5
|
+
# Usage: bash merge-task.sh <project_id> <issue_url | task_branch>
|
|
6
|
+
# arg2 may be a GitHub issue URL (single-issue task) OR the task
|
|
7
|
+
# sub-branch itself (BRANCH.ISSUE-<n1>-<n2>), which the work flow passes
|
|
8
|
+
# directly so combined multi-issue branches merge correctly (POL-070).
|
|
9
|
+
# Compliance: C02 (POL-073 to POL-075)
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
source "$(dirname "$0")/lib.sh"
|
|
13
|
+
load_config
|
|
14
|
+
|
|
15
|
+
# ── Inputs ────────────────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
PROJECT_ID="${1:-}"
|
|
18
|
+
TASK_ARG="${2:-}"
|
|
19
|
+
|
|
20
|
+
[[ -n "$PROJECT_ID" ]] || hard_stop "Usage: $0 <project_id> <issue_url | task_branch>"
|
|
21
|
+
[[ -n "$TASK_ARG" ]] || hard_stop "Usage: $0 <project_id> <issue_url | task_branch>"
|
|
22
|
+
|
|
23
|
+
echo "=== merge-task: $PROJECT_ID / $TASK_ARG"
|
|
24
|
+
echo ""
|
|
25
|
+
|
|
26
|
+
PROJECT_YAML=$(get_project_yaml "$PROJECT_ID")
|
|
27
|
+
check_project_exists "$PROJECT_ID"
|
|
28
|
+
|
|
29
|
+
# ── Pre-conditions ────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
require_project_status "$PROJECT_YAML" "active"
|
|
32
|
+
|
|
33
|
+
# This op merges + pushes + archives branches + closes the issue — all mutating.
|
|
34
|
+
# Gate it on GitHub-Project write access like the other mutating scripts
|
|
35
|
+
# (create-task/seed/resume), per H9.
|
|
36
|
+
CURRENT_USER=$(git config user.email 2>/dev/null || echo "")
|
|
37
|
+
ASSIGNED_TO=$(yaml_get "$PROJECT_YAML" "assigned_to") # display/audit cache
|
|
38
|
+
GH_PROJECT=$(yaml_get "$PROJECT_YAML" "github_project")
|
|
39
|
+
is_authorized_for_project "$GH_PROJECT" "$ASSIGNED_TO" \
|
|
40
|
+
|| hard_stop "You ($CURRENT_USER) are not authorized on this project — you need write access to its GitHub Project ($GH_PROJECT)."
|
|
41
|
+
|
|
42
|
+
BRANCH=$(project_branch_for_id "$PROJECT_ID")
|
|
43
|
+
|
|
44
|
+
# Resolve arg2 → the task sub-branch (TASK_ID) and every issue it closes.
|
|
45
|
+
# Scheme B (POL-070): sub-branch = BRANCH.ISSUE-<n1>-<n2>-…, keyed on issue NUMBERS.
|
|
46
|
+
# - issue URL → TASK_ID = BRANCH.ISSUE-<that number>; closes that one issue.
|
|
47
|
+
# - task branch → TASK_ID = the branch; closes every issue whose number it carries
|
|
48
|
+
# (resolved to a URL via the project board).
|
|
49
|
+
ISSUE_URLS=()
|
|
50
|
+
|
|
51
|
+
# resolve_board_issue_url <number> → the issue's URL on this project's board (or empty).
|
|
52
|
+
resolve_board_issue_url() {
|
|
53
|
+
local want="$1" pnum powner
|
|
54
|
+
pnum=$(echo "$GH_PROJECT" | grep -oE '/projects/[0-9]+' | grep -oE '[0-9]+')
|
|
55
|
+
powner=$(echo "$GH_PROJECT" | sed -E 's|.*/(orgs\|users)/([^/]+)/.*|\2|')
|
|
56
|
+
gh project item-list "$pnum" --owner "$powner" --format json --limit 200 2>/dev/null | python3 -c "
|
|
57
|
+
import sys, json
|
|
58
|
+
want = '$want'
|
|
59
|
+
try: d = json.load(sys.stdin)
|
|
60
|
+
except Exception: sys.exit(0)
|
|
61
|
+
for i in d.get('items', []):
|
|
62
|
+
c = i.get('content') or {}
|
|
63
|
+
if str(c.get('number')) == want and c.get('url'):
|
|
64
|
+
print(c['url']); break
|
|
65
|
+
"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if [[ "$TASK_ARG" == *"/issues/"* ]]; then
|
|
69
|
+
INUM=$(echo "$TASK_ARG" | grep -oE '/issues/[0-9]+' | grep -oE '[0-9]+$') \
|
|
70
|
+
|| hard_stop "Could not parse an issue number from $TASK_ARG"
|
|
71
|
+
[[ -n "$INUM" ]] || hard_stop "Could not parse an issue number from $TASK_ARG"
|
|
72
|
+
TASK_ID="${BRANCH}.ISSUE-${INUM}"
|
|
73
|
+
ISSUE_URLS+=("$TASK_ARG")
|
|
74
|
+
else
|
|
75
|
+
TASK_ID="$TASK_ARG"
|
|
76
|
+
[[ "$TASK_ID" == "${BRANCH}".ISSUE-* ]] \
|
|
77
|
+
|| hard_stop "'$TASK_ID' is not a task sub-branch of '$BRANCH' (expected ${BRANCH}.ISSUE-<n>)."
|
|
78
|
+
SUFFIX="${TASK_ID#"${BRANCH}".ISSUE-}"
|
|
79
|
+
IFS='-' read -ra TASK_NUMS <<< "$SUFFIX"
|
|
80
|
+
for n in "${TASK_NUMS[@]}"; do
|
|
81
|
+
[[ "$n" =~ ^[0-9]+$ ]] || continue
|
|
82
|
+
u="$(resolve_board_issue_url "$n")"
|
|
83
|
+
if [[ -n "$u" ]]; then ISSUE_URLS+=("$u"); else warn "Could not resolve issue #$n on the board — close it manually after merge."; fi
|
|
84
|
+
done
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Verify the task sub-branch exists on the remote
|
|
88
|
+
git -C "$REPO_ROOT" ls-remote --exit-code --heads origin "$TASK_ID" >/dev/null 2>&1 \
|
|
89
|
+
|| hard_stop "No sub-branch '$TASK_ID' on the remote — was the task created?"
|
|
90
|
+
|
|
91
|
+
# Check no uncommitted changes in workspace
|
|
92
|
+
check_clean "$REPO_ROOT"
|
|
93
|
+
|
|
94
|
+
# Check no uncommitted changes in code repos
|
|
95
|
+
while IFS= read -r repo_url; do
|
|
96
|
+
REPO_DIR="$(repo_clone_dir "$PROJECT_ID" "$(get_repo_name "$repo_url")")"
|
|
97
|
+
[[ -e "$REPO_DIR/.git" ]] && check_clean "$REPO_DIR"
|
|
98
|
+
done < <(get_project_repos "$PROJECT_YAML")
|
|
99
|
+
|
|
100
|
+
# ── Merge sub-branch into project branch ─────────────────────────────────────
|
|
101
|
+
# Multi-repo, not transactional: a conflict on a later repo leaves earlier repos
|
|
102
|
+
# already merged+pushed. To make a re-run safe (H5) we detect an already-merged
|
|
103
|
+
# sub-branch with `git merge-base --is-ancestor` and skip it, and we defer ALL
|
|
104
|
+
# archiving until every merge+push has succeeded — so a mid-loop failure never
|
|
105
|
+
# archives some repos and not others.
|
|
106
|
+
|
|
107
|
+
# Merge the sub-branch into the project branch in <path>, idempotently:
|
|
108
|
+
# if $TASK_ID is already an ancestor of $BRANCH, the merge is a no-op and we skip
|
|
109
|
+
# (no checkout/merge/push) so re-runs after a partial failure don't churn.
|
|
110
|
+
merge_task_into_branch() {
|
|
111
|
+
local path="$1" label="$2"
|
|
112
|
+
git -C "$path" fetch origin "$TASK_ID" 2>/dev/null || true
|
|
113
|
+
if git -C "$path" merge-base --is-ancestor "$TASK_ID" "$BRANCH" 2>/dev/null; then
|
|
114
|
+
info "'$TASK_ID' already merged into '$BRANCH' in $label — skipping."
|
|
115
|
+
return 0
|
|
116
|
+
fi
|
|
117
|
+
echo "Merging '$TASK_ID' → '$BRANCH' in $label..."
|
|
118
|
+
merge_branch "$path" "$TASK_ID" "$BRANCH"
|
|
119
|
+
git -C "$path" push origin "$BRANCH"
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
cd "$REPO_ROOT"
|
|
123
|
+
merge_task_into_branch "$REPO_ROOT" "workspace repo"
|
|
124
|
+
|
|
125
|
+
while IFS= read -r repo_url; do
|
|
126
|
+
REPO_NAME=$(get_repo_name "$repo_url")
|
|
127
|
+
REPO_DIR="$(repo_clone_dir "$PROJECT_ID" "$REPO_NAME")"
|
|
128
|
+
if [[ ! -e "$REPO_DIR/.git" ]]; then
|
|
129
|
+
warn "Repo $REPO_NAME not cloned locally — skipping merge."
|
|
130
|
+
continue
|
|
131
|
+
fi
|
|
132
|
+
merge_task_into_branch "$REPO_DIR" "$REPO_NAME"
|
|
133
|
+
done < <(get_project_repos "$PROJECT_YAML")
|
|
134
|
+
|
|
135
|
+
# Reaching here means every merge+push above succeeded (merge_branch exits 2 on
|
|
136
|
+
# conflict). Only now is it safe to archive sub-branches across all repos.
|
|
137
|
+
|
|
138
|
+
# ── Archive sub-branches ──────────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
echo ""
|
|
141
|
+
echo "Archiving sub-branches..."
|
|
142
|
+
|
|
143
|
+
archive_branch "$REPO_ROOT" "$TASK_ID"
|
|
144
|
+
|
|
145
|
+
while IFS= read -r repo_url; do
|
|
146
|
+
REPO_DIR="$(repo_clone_dir "$PROJECT_ID" "$(get_repo_name "$repo_url")")"
|
|
147
|
+
[[ -e "$REPO_DIR/.git" ]] && archive_branch "$REPO_DIR" "$TASK_ID"
|
|
148
|
+
done < <(get_project_repos "$PROJECT_YAML")
|
|
149
|
+
|
|
150
|
+
# ── Close every GitHub Issue the branch covers + mark Done on the board ───────
|
|
151
|
+
GHPROJ=$(yaml_get "$PROJECT_YAML" "github_project")
|
|
152
|
+
for u in "${ISSUE_URLS[@]}"; do
|
|
153
|
+
gh issue close "$u" --comment "Task \`$TASK_ID\` merged into \`$BRANCH\`." 2>/dev/null \
|
|
154
|
+
|| warn "Could not close issue $u — close manually."
|
|
155
|
+
info "Closed issue: $u"
|
|
156
|
+
board_set_status "$GHPROJ" "$u" "Done" || true
|
|
157
|
+
done
|
|
158
|
+
|
|
159
|
+
echo ""
|
|
160
|
+
echo "=== Task merged successfully!"
|
|
161
|
+
echo " Task: $TASK_ID"
|
|
162
|
+
echo " Merged → $BRANCH"
|
|
163
|
+
echo " Issues: ${ISSUE_URLS[*]:-n/a} (closed)"
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Script: onboard-repo
|
|
3
|
+
# Purpose: Initializes the knowledge/ folder structure in an existing code repo,
|
|
4
|
+
# bringing it under the Agentic Development Policy.
|
|
5
|
+
# Usage: bash onboard-repo.sh <repo_url> <repo_description> <repo_owner>
|
|
6
|
+
# Compliance: C02 — repo owner must approve the PR (POL-108)
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
source "$(dirname "$0")/lib.sh"
|
|
10
|
+
load_config
|
|
11
|
+
|
|
12
|
+
# ── Inputs ────────────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
REPO_URL="${1:-}"
|
|
15
|
+
REPO_DESC="${2:-}"
|
|
16
|
+
REPO_OWNER="${3:-}"
|
|
17
|
+
|
|
18
|
+
[[ -n "$REPO_URL" ]] || hard_stop "Usage: $0 <repo_url> <repo_description> <repo_owner>"
|
|
19
|
+
[[ -n "$REPO_DESC" ]] || hard_stop "Usage: $0 <repo_url> <repo_description> <repo_owner>"
|
|
20
|
+
[[ -n "$REPO_OWNER" ]] || hard_stop "Usage: $0 <repo_url> <repo_description> <repo_owner>"
|
|
21
|
+
|
|
22
|
+
REPO_NAME=$(get_repo_name "$REPO_URL")
|
|
23
|
+
ONBOARD_BRANCH="onboard-knowledge"
|
|
24
|
+
|
|
25
|
+
echo "=== onboard-repo: $REPO_URL"
|
|
26
|
+
echo " Description: $REPO_DESC"
|
|
27
|
+
echo " Owner: $REPO_OWNER"
|
|
28
|
+
echo ""
|
|
29
|
+
|
|
30
|
+
# ── Clone or locate repo ──────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
TMP_CLONE=false
|
|
33
|
+
# #65/H6: $PRJ_GOV_LOC was never defined → aborted under `set -u`. Use the
|
|
34
|
+
# resolved AGENT_WORK_ROOT (set by load_config), matching seed.sh/join.sh.
|
|
35
|
+
REPO_DIR="$AGENT_WORK_ROOT/onboard/$REPO_NAME"
|
|
36
|
+
|
|
37
|
+
if [[ -e "$REPO_DIR/.git" ]]; then
|
|
38
|
+
info "Found existing clone at $REPO_DIR — fetching..."
|
|
39
|
+
git -C "$REPO_DIR" fetch origin
|
|
40
|
+
else
|
|
41
|
+
info "Cloning $REPO_URL → $REPO_DIR..."
|
|
42
|
+
mkdir -p "$AGENT_WORK_ROOT/onboard"
|
|
43
|
+
git clone "$REPO_URL" "$REPO_DIR" || hard_stop "Clone failed for $REPO_URL — verify access."
|
|
44
|
+
TMP_CLONE=true
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Detect default branch
|
|
48
|
+
REPO_DEFAULT_BRANCH=$(git -C "$REPO_DIR" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null \
|
|
49
|
+
| sed 's|refs/remotes/origin/||') || REPO_DEFAULT_BRANCH="main"
|
|
50
|
+
|
|
51
|
+
# ── Pre-conditions ────────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
if [[ -d "$REPO_DIR/knowledge" ]]; then
|
|
54
|
+
hard_stop "knowledge/ already exists in $REPO_NAME — investigate existing structure."
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if git -C "$REPO_DIR" ls-remote --exit-code origin "$ONBOARD_BRANCH" &>/dev/null; then
|
|
58
|
+
hard_stop "Branch '$ONBOARD_BRANCH' already exists in $REPO_NAME — investigate before proceeding."
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# ── Create onboard-knowledge branch ──────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
git -C "$REPO_DIR" checkout "$REPO_DEFAULT_BRANCH"
|
|
64
|
+
git -C "$REPO_DIR" pull origin "$REPO_DEFAULT_BRANCH" 2>/dev/null || true
|
|
65
|
+
git -C "$REPO_DIR" checkout -b "$ONBOARD_BRANCH"
|
|
66
|
+
|
|
67
|
+
# ── Scaffold knowledge/ folder ────────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
mkdir -p "$REPO_DIR/knowledge/repo"
|
|
70
|
+
|
|
71
|
+
# knowledge/agent.md — from repo-agent-template
|
|
72
|
+
cat > "$REPO_DIR/knowledge/agent.md" <<MD
|
|
73
|
+
# $REPO_NAME — Agent Entry Point
|
|
74
|
+
|
|
75
|
+
**Repository:** $REPO_URL
|
|
76
|
+
**Purpose:** $REPO_DESC
|
|
77
|
+
**Owner:** $REPO_OWNER
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Important: Knowledge Layer Priority
|
|
82
|
+
|
|
83
|
+
This file represents the **repo-local knowledge layer** — third priority.
|
|
84
|
+
|
|
85
|
+
\`\`\`
|
|
86
|
+
1. Org-wide knowledge → $WORKSPACE_REPO/knowledge/ [HIGHEST]
|
|
87
|
+
2. Project knowledge → $WORKSPACE_REPO/projects/<project-id>/knowledge/
|
|
88
|
+
3. This repo's knowledge → this file and knowledge/repo/ [THIS FILE]
|
|
89
|
+
4. Your developer prefs → $AGENT_WORK_ROOT/preferences/<your-gh-login>.md
|
|
90
|
+
\`\`\`
|
|
91
|
+
|
|
92
|
+
**This file cannot override org-wide knowledge or policy.**
|
|
93
|
+
See \`$WORKSPACE_REPO/knowledge/policies/agentic-development-policy.md\`.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Repo Knowledge
|
|
98
|
+
|
|
99
|
+
Read the following before working in this repository:
|
|
100
|
+
|
|
101
|
+
- \`knowledge/repo/structure.md\` — directory layout, modules, packages
|
|
102
|
+
- \`knowledge/repo/environment.md\` — build tools, dependencies, setup instructions
|
|
103
|
+
- \`knowledge/repo/patterns.md\` — coding conventions, architectural patterns
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Write Restrictions
|
|
108
|
+
|
|
109
|
+
During an active project:
|
|
110
|
+
- Do NOT modify \`knowledge/repo/\` directly
|
|
111
|
+
- All knowledge writes go to \`$WORKSPACE_REPO/projects/<project-id>/knowledge/\`
|
|
112
|
+
- Repo knowledge is updated only via the project's knowledge close PR
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Data Classification Reminder
|
|
117
|
+
|
|
118
|
+
Never commit credentials, secrets, API keys, or PII (C01).
|
|
119
|
+
See \`$WORKSPACE_REPO/knowledge/policies/data-classification.md\`.
|
|
120
|
+
MD
|
|
121
|
+
|
|
122
|
+
# knowledge/repo/structure.md — placeholder
|
|
123
|
+
cat > "$REPO_DIR/knowledge/repo/structure.md" <<MD
|
|
124
|
+
# $REPO_NAME — Repository Structure
|
|
125
|
+
|
|
126
|
+
**Owner:** $REPO_OWNER
|
|
127
|
+
**TODO:** Populate this file with the repository's directory layout.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Directory Layout
|
|
132
|
+
|
|
133
|
+
\`\`\`
|
|
134
|
+
<describe the top-level directories and their purpose>
|
|
135
|
+
\`\`\`
|
|
136
|
+
|
|
137
|
+
## Key Modules / Packages
|
|
138
|
+
|
|
139
|
+
- \`<module>\` — <description>
|
|
140
|
+
|
|
141
|
+
## Entry Points
|
|
142
|
+
|
|
143
|
+
- \`<main file or command>\` — <description>
|
|
144
|
+
MD
|
|
145
|
+
|
|
146
|
+
# knowledge/repo/environment.md — placeholder
|
|
147
|
+
cat > "$REPO_DIR/knowledge/repo/environment.md" <<MD
|
|
148
|
+
# $REPO_NAME — Environment & Setup
|
|
149
|
+
|
|
150
|
+
**Owner:** $REPO_OWNER
|
|
151
|
+
**TODO:** Populate this file with build tools, dependencies, and local setup.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Prerequisites
|
|
156
|
+
|
|
157
|
+
- <tool> <version>
|
|
158
|
+
- <tool> <version>
|
|
159
|
+
|
|
160
|
+
## Local Setup
|
|
161
|
+
|
|
162
|
+
\`\`\`bash
|
|
163
|
+
# Steps to get this repo running locally
|
|
164
|
+
\`\`\`
|
|
165
|
+
|
|
166
|
+
## Environment Variables
|
|
167
|
+
|
|
168
|
+
| Variable | Required | Description |
|
|
169
|
+
|---|---|---|
|
|
170
|
+
| \`ENV_VAR\` | Yes | Description |
|
|
171
|
+
|
|
172
|
+
## Running Tests
|
|
173
|
+
|
|
174
|
+
\`\`\`bash
|
|
175
|
+
# How to run the test suite
|
|
176
|
+
\`\`\`
|
|
177
|
+
MD
|
|
178
|
+
|
|
179
|
+
# knowledge/repo/patterns.md — placeholder
|
|
180
|
+
cat > "$REPO_DIR/knowledge/repo/patterns.md" <<MD
|
|
181
|
+
# $REPO_NAME — Patterns & Conventions
|
|
182
|
+
|
|
183
|
+
**Owner:** $REPO_OWNER
|
|
184
|
+
**TODO:** Populate this file with coding conventions and architectural patterns.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Coding Style
|
|
189
|
+
|
|
190
|
+
- Language: <language>
|
|
191
|
+
- Linter / formatter: <tool>
|
|
192
|
+
- Key conventions: <describe>
|
|
193
|
+
|
|
194
|
+
## Architectural Patterns
|
|
195
|
+
|
|
196
|
+
- <pattern name>: <description>
|
|
197
|
+
|
|
198
|
+
## Common Pitfalls
|
|
199
|
+
|
|
200
|
+
- <pitfall>: <how to avoid>
|
|
201
|
+
MD
|
|
202
|
+
|
|
203
|
+
info "Scaffolded knowledge/ folder."
|
|
204
|
+
|
|
205
|
+
# ── Commit and push ───────────────────────────────────────────────────────────
|
|
206
|
+
|
|
207
|
+
git -C "$REPO_DIR" add knowledge/
|
|
208
|
+
git -C "$REPO_DIR" commit -m "onboard: initialize knowledge/ folder for agentic development"
|
|
209
|
+
git -C "$REPO_DIR" push -u origin "$ONBOARD_BRANCH" \
|
|
210
|
+
|| hard_stop "Push failed for $REPO_URL — verify push access."
|
|
211
|
+
|
|
212
|
+
info "Branch '$ONBOARD_BRANCH' pushed."
|
|
213
|
+
|
|
214
|
+
# ── Raise PR ──────────────────────────────────────────────────────────────────
|
|
215
|
+
|
|
216
|
+
echo "Raising PR..."
|
|
217
|
+
|
|
218
|
+
PR_BODY=$(cat <<MD
|
|
219
|
+
## [Onboard] Initialize \`knowledge/\` folder for agentic development
|
|
220
|
+
|
|
221
|
+
This PR adds the \`knowledge/\` folder structure to bring **$REPO_NAME** under the
|
|
222
|
+
$ORG_NAME Agentic Development Policy.
|
|
223
|
+
|
|
224
|
+
### What was added
|
|
225
|
+
|
|
226
|
+
- \`knowledge/agent.md\` — agent entry point with knowledge layer priority
|
|
227
|
+
- \`knowledge/repo/structure.md\` — placeholder for repo structure
|
|
228
|
+
- \`knowledge/repo/environment.md\` — placeholder for build/setup instructions
|
|
229
|
+
- \`knowledge/repo/patterns.md\` — placeholder for coding conventions
|
|
230
|
+
|
|
231
|
+
### What the repo owner needs to do after merging
|
|
232
|
+
|
|
233
|
+
Please populate the placeholder files with accurate information:
|
|
234
|
+
|
|
235
|
+
1. **\`knowledge/repo/structure.md\`** — describe the directory layout and key modules
|
|
236
|
+
2. **\`knowledge/repo/environment.md\`** — document build tools, env vars, setup steps
|
|
237
|
+
3. **\`knowledge/repo/patterns.md\`** — document coding conventions and architectural patterns
|
|
238
|
+
|
|
239
|
+
Submit these as a follow-up PR directly in this repo.
|
|
240
|
+
|
|
241
|
+
### What this PR does NOT do
|
|
242
|
+
|
|
243
|
+
- Does not modify CI/CD pipelines
|
|
244
|
+
- Does not add application code
|
|
245
|
+
- Does not enforce any structural changes beyond adding \`knowledge/\`
|
|
246
|
+
|
|
247
|
+
*Generated by onboard-repo.sh*
|
|
248
|
+
MD
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
PR_URL=$(gh pr create \
|
|
252
|
+
--repo "$REPO_URL" \
|
|
253
|
+
--base "$REPO_DEFAULT_BRANCH" \
|
|
254
|
+
--head "$ONBOARD_BRANCH" \
|
|
255
|
+
--title "[Onboard] Initialize knowledge/ folder for agentic development" \
|
|
256
|
+
--body "$PR_BODY" \
|
|
257
|
+
2>/dev/null) \
|
|
258
|
+
|| {
|
|
259
|
+
warn "PR creation failed — retrying..."
|
|
260
|
+
PR_URL=$(gh pr create \
|
|
261
|
+
--repo "$REPO_URL" \
|
|
262
|
+
--base "$REPO_DEFAULT_BRANCH" \
|
|
263
|
+
--head "$ONBOARD_BRANCH" \
|
|
264
|
+
--title "[Onboard] Initialize knowledge/ folder for agentic development" \
|
|
265
|
+
--body "$PR_BODY")
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
echo ""
|
|
269
|
+
echo "=== Onboarding PR created!"
|
|
270
|
+
echo " PR: $PR_URL"
|
|
271
|
+
echo ""
|
|
272
|
+
echo " After the repo owner merges this PR, they should populate:"
|
|
273
|
+
echo " - knowledge/repo/structure.md"
|
|
274
|
+
echo " - knowledge/repo/environment.md"
|
|
275
|
+
echo " - knowledge/repo/patterns.md"
|
package/scripts/pause.sh
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Script: pause
|
|
3
|
+
# Purpose: Transitions a project from ACTIVE to PAUSED.
|
|
4
|
+
# Preserves all state for later resumption.
|
|
5
|
+
# Usage: bash pause.sh <project_id>
|
|
6
|
+
# Compliance: C02 (POL-049, POL-051)
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
source "$(dirname "$0")/lib.sh"
|
|
10
|
+
load_config
|
|
11
|
+
|
|
12
|
+
# ── Inputs ────────────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
PROJECT_ID="${1:-}"
|
|
15
|
+
[[ -n "$PROJECT_ID" ]] || hard_stop "Usage: $0 <project_id>"
|
|
16
|
+
|
|
17
|
+
echo "=== pause: $PROJECT_ID"
|
|
18
|
+
echo ""
|
|
19
|
+
|
|
20
|
+
PROJECT_YAML=$(get_project_yaml "$PROJECT_ID")
|
|
21
|
+
check_project_exists "$PROJECT_ID"
|
|
22
|
+
|
|
23
|
+
# ── Pre-conditions ────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
require_project_status "$PROJECT_YAML" "active"
|
|
26
|
+
|
|
27
|
+
CURRENT_USER=$(git config user.email 2>/dev/null || echo "")
|
|
28
|
+
ASSIGNED_TO=$(yaml_get "$PROJECT_YAML" "assigned_to") # display/audit cache
|
|
29
|
+
GH_PROJECT=$(yaml_get "$PROJECT_YAML" "github_project")
|
|
30
|
+
is_authorized_for_project "$GH_PROJECT" "$ASSIGNED_TO" \
|
|
31
|
+
|| hard_stop "Not authorized to pause — '$CURRENT_USER' needs write access to the project's GitHub Project ($GH_PROJECT)."
|
|
32
|
+
|
|
33
|
+
BRANCH=$(project_branch_for_id "$PROJECT_ID")
|
|
34
|
+
|
|
35
|
+
echo "Checking for uncommitted changes..."
|
|
36
|
+
|
|
37
|
+
check_clean "$REPO_ROOT"
|
|
38
|
+
|
|
39
|
+
while IFS= read -r repo_url; do
|
|
40
|
+
REPO_DIR="$(repo_clone_dir "$PROJECT_ID" "$(get_repo_name "$repo_url")")"
|
|
41
|
+
[[ -e "$REPO_DIR/.git" ]] && check_clean "$REPO_DIR"
|
|
42
|
+
done < <(get_project_repos "$PROJECT_YAML")
|
|
43
|
+
|
|
44
|
+
info "All repos are clean."
|
|
45
|
+
|
|
46
|
+
# ── Update project.yaml ───────────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
TODAY=$(today)
|
|
49
|
+
yaml_set "$PROJECT_YAML" "status" "paused"
|
|
50
|
+
yaml_set "$PROJECT_YAML" "paused_at" "$TODAY"
|
|
51
|
+
|
|
52
|
+
# ── Push all branches ─────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
cd "$REPO_ROOT"
|
|
55
|
+
git checkout "$BRANCH"
|
|
56
|
+
git add "projects/$PROJECT_ID/project.yaml"
|
|
57
|
+
git commit -m "pause: $PROJECT_ID"
|
|
58
|
+
git push origin "$BRANCH"
|
|
59
|
+
|
|
60
|
+
while IFS= read -r repo_url; do
|
|
61
|
+
REPO_DIR="$(repo_clone_dir "$PROJECT_ID" "$(get_repo_name "$repo_url")")"
|
|
62
|
+
if [[ -e "$REPO_DIR/.git" ]]; then
|
|
63
|
+
git -C "$REPO_DIR" push origin "$BRANCH" 2>/dev/null || warn "Push skipped for $repo_url (nothing to push)"
|
|
64
|
+
fi
|
|
65
|
+
done < <(get_project_repos "$PROJECT_YAML")
|
|
66
|
+
|
|
67
|
+
# ── Reflect pause in the registry index on the default branch + README mirror ─
|
|
68
|
+
# project.yaml status lives on the project branch; the authoritative index lives
|
|
69
|
+
# on $DEFAULT_BRANCH. Flip it so `prj list`/`prj status` don't show a paused
|
|
70
|
+
# project as active.
|
|
71
|
+
registry_set_status_on_main "$PROJECT_ID" "paused"
|
|
72
|
+
project_readme_mirror "$PROJECT_ID" "$(yaml_get "$PROJECT_YAML" github_project)" "paused" \
|
|
73
|
+
"$(yaml_get "$PROJECT_YAML" assigned_to)" "$(yaml_get "$PROJECT_YAML" seeded_by)" "$BRANCH" || true
|
|
74
|
+
|
|
75
|
+
echo ""
|
|
76
|
+
echo "=== Project paused."
|
|
77
|
+
echo " Status: paused"
|
|
78
|
+
echo " paused_at: $TODAY"
|
|
79
|
+
echo ""
|
|
80
|
+
echo " Resume with: bash resume.sh $PROJECT_ID"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Script: project-access
|
|
3
|
+
# Purpose: Grant or revoke WRITE access on a GitHub Project v2 — the ADR-0001
|
|
4
|
+
# Phase 3 source of truth for assignment (access = authorization).
|
|
5
|
+
# Wraps lib.sh's gh_* helpers so the prj CLI (which does not source
|
|
6
|
+
# lib.sh) can sync GitHub access from `manage assign/unassign/reassign`.
|
|
7
|
+
# Usage: bash project-access.sh <grant|revoke> <github_project_url> <login-or-@team>
|
|
8
|
+
# Note: MUTATES real GitHub Project permissions.
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
source "$(dirname "$0")/lib.sh"
|
|
11
|
+
load_config
|
|
12
|
+
|
|
13
|
+
ACTION="${1:-}"; URL="${2:-}"; WHO="${3:-}"
|
|
14
|
+
[[ -n "$ACTION" && -n "$URL" && -n "$WHO" ]] \
|
|
15
|
+
|| hard_stop "Usage: $0 <grant|revoke> <github_project_url> <login-or-@team>"
|
|
16
|
+
|
|
17
|
+
case "$ACTION" in
|
|
18
|
+
grant) ROLE=WRITER ;;
|
|
19
|
+
revoke) ROLE=NONE ;;
|
|
20
|
+
*) hard_stop "Unknown action '$ACTION' (expected grant|revoke)." ;;
|
|
21
|
+
esac
|
|
22
|
+
|
|
23
|
+
PROJ_ID=$(gh_project_node_id "$URL") \
|
|
24
|
+
|| hard_stop "Could not resolve a GitHub Project from '$URL' (check access / token scopes)."
|
|
25
|
+
|
|
26
|
+
ACTOR=$(gh_resolve_actor "$WHO") \
|
|
27
|
+
|| hard_stop "Could not resolve '$WHO' to a GitHub user or team. Use a GitHub login, or '@team-slug'."
|
|
28
|
+
read -r KIND AID <<< "$ACTOR"
|
|
29
|
+
|
|
30
|
+
if gh_project_set_access "$PROJ_ID" "$KIND" "$AID" "$ROLE"; then
|
|
31
|
+
info "GitHub Project access: ${ACTION}ed '$WHO' ($KIND) — role $ROLE."
|
|
32
|
+
else
|
|
33
|
+
hard_stop "GitHub API call failed. Set access manually in the Project's Manage access."
|
|
34
|
+
fi
|