@ngocsangairvds/vsaf 4.0.8 → 4.0.10
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/package.json +1 -1
- package/packages/cli/dist/commands/install.d.ts.map +1 -1
- package/packages/cli/dist/commands/install.js +12 -0
- package/packages/cli/dist/commands/install.js.map +1 -1
- package/skills/sdlc/install-deps.mjs +19 -3
- package/skills/vds-skill/_shared/config-check.js +76 -0
- package/skills/vds-skill/_shared/credentials.js +139 -0
- package/skills/vds-skill/create-bitbucket-pr/SKILL.md +2 -18
- package/skills/vds-skill/create-bitbucket-pr/scripts/create-pr.js +125 -0
- package/skills/vds-skill/create-jira-epic/SKILL.md +2 -20
- package/skills/vds-skill/create-jira-epic/scripts/create-epic.js +120 -0
- package/skills/vds-skill/install-deps.mjs +34 -32
- package/skills/vds-skill/pull/SKILL.md +1 -1
- package/skills/vds-skill/pull/scripts/pull.js +59 -0
- package/skills/vds-skill/push-prd/SKILL.md +11 -30
- package/skills/vds-skill/push-srs/SKILL.md +4 -23
- package/skills/vds-skill/search-confluence/SKILL.md +2 -22
- package/skills/vds-skill/search-confluence/scripts/search.js +114 -0
- package/skills/vds-skill/vds-scripts-skill/SKILL.md +3 -3
- package/skills/vds-skill/_shared/credentials.sh +0 -79
- package/skills/vds-skill/create-bitbucket-pr/scripts/create-pr.sh +0 -105
- package/skills/vds-skill/create-jira-epic/scripts/create-epic.sh +0 -113
- package/skills/vds-skill/pull/scripts/pull.sh +0 -52
- package/skills/vds-skill/search-confluence/scripts/search.sh +0 -128
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# vds-skill-create-bitbucket-pr: create Bitbucket PR via vds-cli
|
|
3
|
-
# Usage: create-pr.sh [--dry-run] [--target BRANCH] [--description-file FILE] [--title TITLE]
|
|
4
|
-
# Auto-extracts project/repo from `git remote get-url origin`.
|
|
5
|
-
|
|
6
|
-
# NOTE: No `set -e` — we want full control of the exit-code path.
|
|
7
|
-
|
|
8
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
|
-
# shellcheck source=/dev/null
|
|
10
|
-
source "$SCRIPT_DIR/../../_shared/vds-skill/credentials.sh"
|
|
11
|
-
|
|
12
|
-
require_command git
|
|
13
|
-
# Note: require_command vds-cli moved AFTER dry-run check.
|
|
14
|
-
|
|
15
|
-
DRY_RUN=false
|
|
16
|
-
TARGET_BRANCH="master"
|
|
17
|
-
DESC_FILE=""
|
|
18
|
-
TITLE=""
|
|
19
|
-
|
|
20
|
-
while [[ $# -gt 0 ]]; do
|
|
21
|
-
case "$1" in
|
|
22
|
-
--dry-run) DRY_RUN=true; shift ;;
|
|
23
|
-
--target) TARGET_BRANCH="$2"; shift 2 ;;
|
|
24
|
-
--description-file) DESC_FILE="$2"; shift 2 ;;
|
|
25
|
-
--title) TITLE="$2"; shift 2 ;;
|
|
26
|
-
*) echo "Unknown arg: $1" >&2; exit 2 ;;
|
|
27
|
-
esac
|
|
28
|
-
done
|
|
29
|
-
|
|
30
|
-
REMOTE_URL=$(git remote get-url origin 2>/dev/null || true)
|
|
31
|
-
if [[ -z "$REMOTE_URL" ]]; then
|
|
32
|
-
echo "ERROR: No git remote 'origin' configured" >&2
|
|
33
|
-
exit 1
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
if [[ ! "$REMOTE_URL" =~ bitbucket\.digital\.vn ]]; then
|
|
37
|
-
echo "WARNING: Remote URL does not match bitbucket.digital.vn pattern:" >&2
|
|
38
|
-
echo " $REMOTE_URL" >&2
|
|
39
|
-
echo " This skill is for Viettel Bitbucket. For GitHub, use 'gh pr create'." >&2
|
|
40
|
-
exit 1
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
|
-
# Extract PROJECT/REPO from URL
|
|
44
|
-
# Handles:
|
|
45
|
-
# ssh://git@bitbucket.digital.vn/PROJECT/repo.git
|
|
46
|
-
# ssh://git@bitbucket.digital.vn:7999/PROJECT/repo.git
|
|
47
|
-
# https://bitbucket.digital.vn/scm/PROJECT/repo.git
|
|
48
|
-
if [[ "$REMOTE_URL" =~ /scm/([^/]+)/([^/]+)\.git$ ]]; then
|
|
49
|
-
PROJECT="${BASH_REMATCH[1]}"
|
|
50
|
-
REPO="${BASH_REMATCH[2]}"
|
|
51
|
-
elif [[ "$REMOTE_URL" =~ /([^/]+)/([^/]+)\.git$ ]]; then
|
|
52
|
-
PROJECT="${BASH_REMATCH[1]}"
|
|
53
|
-
REPO="${BASH_REMATCH[2]}"
|
|
54
|
-
else
|
|
55
|
-
echo "ERROR: Cannot parse PROJECT/REPO from remote URL: $REMOTE_URL" >&2
|
|
56
|
-
exit 1
|
|
57
|
-
fi
|
|
58
|
-
|
|
59
|
-
SOURCE_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
60
|
-
if [[ -z "$SOURCE_BRANCH" ]] || [[ "$SOURCE_BRANCH" == "HEAD" ]]; then
|
|
61
|
-
echo "ERROR: Not on a named branch" >&2
|
|
62
|
-
exit 1
|
|
63
|
-
fi
|
|
64
|
-
|
|
65
|
-
if [[ -z "$TITLE" ]]; then
|
|
66
|
-
TITLE=$(git log -1 --pretty=%s)
|
|
67
|
-
fi
|
|
68
|
-
|
|
69
|
-
if [[ -z "$DESC_FILE" ]]; then
|
|
70
|
-
DESC_FILE=$(find .vsaf/docs/features -name '09-ship.md' 2>/dev/null | head -1)
|
|
71
|
-
[[ -z "$DESC_FILE" ]] && DESC_FILE=$(find .vsaf/docs/hotfixes -name '03-ship.md' 2>/dev/null | head -1)
|
|
72
|
-
fi
|
|
73
|
-
|
|
74
|
-
CMD=(vds-cli bitbucket pr create "$PROJECT/$REPO"
|
|
75
|
-
--source "$SOURCE_BRANCH"
|
|
76
|
-
--target "$TARGET_BRANCH"
|
|
77
|
-
--title "$TITLE")
|
|
78
|
-
[[ -n "$DESC_FILE" ]] && [[ -f "$DESC_FILE" ]] && CMD+=(--description-file "$DESC_FILE")
|
|
79
|
-
|
|
80
|
-
if [[ "$DRY_RUN" == "true" ]]; then
|
|
81
|
-
echo "DRY-RUN — would execute:"
|
|
82
|
-
printf ' %q' "${CMD[@]}"
|
|
83
|
-
echo ""
|
|
84
|
-
echo " + --yes --json-only"
|
|
85
|
-
exit 0
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
require_command vds-cli
|
|
89
|
-
|
|
90
|
-
ensure_env VDS_BITBUCKET_TOKEN "Enter VDS Bitbucket personal access token"
|
|
91
|
-
|
|
92
|
-
echo "About to create PR:"
|
|
93
|
-
echo " Project/Repo: $PROJECT/$REPO"
|
|
94
|
-
echo " Source: $SOURCE_BRANCH"
|
|
95
|
-
echo " Target: $TARGET_BRANCH"
|
|
96
|
-
echo " Title: $TITLE"
|
|
97
|
-
echo " Description: ${DESC_FILE:-<empty>}"
|
|
98
|
-
echo ""
|
|
99
|
-
read -rp "Proceed? [y/N]: " confirm
|
|
100
|
-
if [[ "$confirm" != "y" ]] && [[ "$confirm" != "Y" ]]; then
|
|
101
|
-
echo "Aborted"
|
|
102
|
-
exit 1
|
|
103
|
-
fi
|
|
104
|
-
|
|
105
|
-
"${CMD[@]}" --yes --json-only
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# vds-skill-create-jira-epic: create a Jira Epic via vds-cli
|
|
3
|
-
# Usage: create-epic.sh [--dry-run] [--project KEY] [--description-file FILE] [--feature NAME]
|
|
4
|
-
|
|
5
|
-
# NOTE: No `set -e` — we want full control of the exit-code path.
|
|
6
|
-
|
|
7
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
-
# shellcheck source=/dev/null
|
|
9
|
-
source "$SCRIPT_DIR/../../_shared/vds-skill/credentials.sh"
|
|
10
|
-
|
|
11
|
-
require_command python3
|
|
12
|
-
# Note: require_command vds-cli moved AFTER dry-run check so --dry-run
|
|
13
|
-
# works without vds-cli installed (preview mode).
|
|
14
|
-
|
|
15
|
-
DRY_RUN=false
|
|
16
|
-
PROJECT_KEY=""
|
|
17
|
-
DESC_FILE=""
|
|
18
|
-
FEATURE_NAME=""
|
|
19
|
-
|
|
20
|
-
while [[ $# -gt 0 ]]; do
|
|
21
|
-
case "$1" in
|
|
22
|
-
--dry-run) DRY_RUN=true; shift ;;
|
|
23
|
-
--project) PROJECT_KEY="$2"; shift 2 ;;
|
|
24
|
-
--description-file) DESC_FILE="$2"; shift 2 ;;
|
|
25
|
-
--feature) FEATURE_NAME="$2"; shift 2 ;;
|
|
26
|
-
*) echo "Unknown arg: $1" >&2; exit 2 ;;
|
|
27
|
-
esac
|
|
28
|
-
done
|
|
29
|
-
|
|
30
|
-
# Determine PRD file path
|
|
31
|
-
if [[ -z "$DESC_FILE" ]]; then
|
|
32
|
-
if [[ -n "$FEATURE_NAME" ]]; then
|
|
33
|
-
for path in ".vsaf/docs/features/$FEATURE_NAME/02-prd.md"; do
|
|
34
|
-
[[ -f "$path" ]] && DESC_FILE="$path" && break
|
|
35
|
-
done
|
|
36
|
-
fi
|
|
37
|
-
|
|
38
|
-
# Fallback: most recent 02-prd.md
|
|
39
|
-
if [[ -z "$DESC_FILE" ]]; then
|
|
40
|
-
DESC_FILE=$(find .vsaf/docs/features -name '02-prd.md' 2>/dev/null \
|
|
41
|
-
| xargs -I{} ls -t {} 2>/dev/null | head -1)
|
|
42
|
-
fi
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
if [[ -z "$DESC_FILE" ]] || [[ ! -f "$DESC_FILE" ]]; then
|
|
46
|
-
echo "ERROR: PRD file not found. Run /sdlc-prd first or specify --description-file" >&2
|
|
47
|
-
exit 1
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
# Derive feature name from PRD path if not given
|
|
51
|
-
if [[ -z "$FEATURE_NAME" ]]; then
|
|
52
|
-
FEATURE_NAME=$(basename "$(dirname "$DESC_FILE")")
|
|
53
|
-
fi
|
|
54
|
-
|
|
55
|
-
# Extract summary from PRD (first H1)
|
|
56
|
-
SUMMARY=$(grep -m1 '^# ' "$DESC_FILE" | sed 's/^# //' || true)
|
|
57
|
-
[[ -z "$SUMMARY" ]] && SUMMARY="$FEATURE_NAME"
|
|
58
|
-
|
|
59
|
-
if [[ "$DRY_RUN" == "true" ]]; then
|
|
60
|
-
DISPLAY_PROJECT="${PROJECT_KEY:-${VDS_JIRA_PROJECT_DEFAULT:-<VDS_JIRA_PROJECT_DEFAULT>}}"
|
|
61
|
-
CMD_DRY=(vds-cli jira create
|
|
62
|
-
--project "$DISPLAY_PROJECT"
|
|
63
|
-
--issuetype Epic
|
|
64
|
-
--summary "$SUMMARY"
|
|
65
|
-
--description-file "$DESC_FILE")
|
|
66
|
-
echo "DRY-RUN — would execute:"
|
|
67
|
-
printf ' %q' "${CMD_DRY[@]}"
|
|
68
|
-
echo ""
|
|
69
|
-
echo " + --yes --json-only"
|
|
70
|
-
exit 0
|
|
71
|
-
fi
|
|
72
|
-
|
|
73
|
-
require_command vds-cli
|
|
74
|
-
|
|
75
|
-
# Ensure credentials
|
|
76
|
-
ensure_env VDS_JIRA_TOKEN "Enter VDS Jira personal access token"
|
|
77
|
-
ensure_env VDS_JIRA_PROJECT_DEFAULT "Enter default Jira project key (e.g. NTTC)" false
|
|
78
|
-
|
|
79
|
-
PROJECT_KEY="${PROJECT_KEY:-$VDS_JIRA_PROJECT_DEFAULT}"
|
|
80
|
-
|
|
81
|
-
CMD=(vds-cli jira create
|
|
82
|
-
--project "$PROJECT_KEY"
|
|
83
|
-
--issuetype Epic
|
|
84
|
-
--summary "$SUMMARY"
|
|
85
|
-
--description-file "$DESC_FILE")
|
|
86
|
-
|
|
87
|
-
echo "About to create Jira Epic:"
|
|
88
|
-
echo " Project: $PROJECT_KEY"
|
|
89
|
-
echo " Summary: $SUMMARY"
|
|
90
|
-
echo " Description: $DESC_FILE"
|
|
91
|
-
echo " Feature: $FEATURE_NAME"
|
|
92
|
-
echo ""
|
|
93
|
-
read -rp "Proceed? [y/N]: " confirm
|
|
94
|
-
if [[ "$confirm" != "y" ]] && [[ "$confirm" != "Y" ]]; then
|
|
95
|
-
echo "Aborted"
|
|
96
|
-
exit 1
|
|
97
|
-
fi
|
|
98
|
-
|
|
99
|
-
RESULT=$("${CMD[@]}" --yes --json-only)
|
|
100
|
-
EPIC_KEY=$(echo "$RESULT" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("key",""))')
|
|
101
|
-
|
|
102
|
-
if [[ -z "$EPIC_KEY" ]]; then
|
|
103
|
-
echo "ERROR: Failed to extract epic key from vds-cli response" >&2
|
|
104
|
-
echo "Response: $RESULT" >&2
|
|
105
|
-
exit 1
|
|
106
|
-
fi
|
|
107
|
-
|
|
108
|
-
EPIC_KEY_FILE="$(dirname "$DESC_FILE")/jira-epic-key.txt"
|
|
109
|
-
echo "$EPIC_KEY" > "$EPIC_KEY_FILE"
|
|
110
|
-
|
|
111
|
-
echo ""
|
|
112
|
-
echo "✓ Created Jira Epic: $EPIC_KEY"
|
|
113
|
-
echo " Saved key to: $EPIC_KEY_FILE"
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# vds-skill-pull: git pull + detect stale local knowledge index
|
|
3
|
-
# Exit codes: forwards `git pull` exit code (0 on success even if knowledge stale)
|
|
4
|
-
|
|
5
|
-
# Run git pull, forwarding all args. Capture exit code for explicit forwarding.
|
|
6
|
-
# (No `set -e` — we want full control of the exit-code path for the advisory stale check.)
|
|
7
|
-
git pull "$@"
|
|
8
|
-
EXIT=$?
|
|
9
|
-
|
|
10
|
-
if [[ $EXIT -ne 0 ]]; then
|
|
11
|
-
exit $EXIT
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
# Skip stale check if not a fetch-based pull (e.g., --no-rebase --quiet might skip FETCH_HEAD)
|
|
15
|
-
if [[ ! -f .git/FETCH_HEAD ]]; then
|
|
16
|
-
exit 0
|
|
17
|
-
fi
|
|
18
|
-
|
|
19
|
-
FETCH_HEAD_MTIME=$(stat -c %Y .git/FETCH_HEAD 2>/dev/null || stat -f %m .git/FETCH_HEAD 2>/dev/null || echo 0)
|
|
20
|
-
STALE_REASONS=()
|
|
21
|
-
|
|
22
|
-
# Check .gitnexus/
|
|
23
|
-
if [[ -d .gitnexus ]]; then
|
|
24
|
-
GITNEXUS_MTIME=$(stat -c %Y .gitnexus 2>/dev/null || stat -f %m .gitnexus 2>/dev/null || echo 0)
|
|
25
|
-
if [[ $GITNEXUS_MTIME -lt $FETCH_HEAD_MTIME ]]; then
|
|
26
|
-
STALE_REASONS+=(".gitnexus/ index older than fetched commits")
|
|
27
|
-
fi
|
|
28
|
-
fi
|
|
29
|
-
# Note: .gitnexus missing is OK (project may not use GitNexus)
|
|
30
|
-
|
|
31
|
-
# Check graphify-out/graph.json
|
|
32
|
-
if [[ -f graphify-out/graph.json ]]; then
|
|
33
|
-
GRAPH_MTIME=$(stat -c %Y graphify-out/graph.json 2>/dev/null || stat -f %m graphify-out/graph.json 2>/dev/null || echo 0)
|
|
34
|
-
if [[ $GRAPH_MTIME -lt $FETCH_HEAD_MTIME ]]; then
|
|
35
|
-
STALE_REASONS+=("graphify-out/graph.json older than fetched commits")
|
|
36
|
-
fi
|
|
37
|
-
fi
|
|
38
|
-
# Note: graphify-out missing is OK
|
|
39
|
-
|
|
40
|
-
# Print suggestion if anything stale
|
|
41
|
-
if [[ ${#STALE_REASONS[@]} -gt 0 ]]; then
|
|
42
|
-
echo ""
|
|
43
|
-
echo "⚠️ Knowledge index có thể stale sau pull:"
|
|
44
|
-
for reason in "${STALE_REASONS[@]}"; do
|
|
45
|
-
echo " - $reason"
|
|
46
|
-
done
|
|
47
|
-
echo ""
|
|
48
|
-
echo " Khuyến nghị: chạy /sdlc-onboard-code để rebuild GitNexus + Graphify locally."
|
|
49
|
-
echo ""
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
exit 0
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# vds-skill-search-confluence: search Confluence + Jira for feature discovery context
|
|
3
|
-
# Usage: search.sh --feature NAME --query KEYWORDS [--dry-run] [--days N] [--limit N]
|
|
4
|
-
|
|
5
|
-
# NOTE: No `set -e` — we want full control of the exit-code path.
|
|
6
|
-
|
|
7
|
-
# Source credentials helper (deployed path: .claude/skills/_shared/vds-skill/credentials.sh)
|
|
8
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
|
-
# shellcheck source=/dev/null
|
|
10
|
-
source "$SCRIPT_DIR/../../_shared/vds-skill/credentials.sh"
|
|
11
|
-
|
|
12
|
-
require_command python3
|
|
13
|
-
# Note: require_command vds-cli moved AFTER dry-run check so --dry-run
|
|
14
|
-
# works without vds-cli installed (preview mode).
|
|
15
|
-
|
|
16
|
-
FEATURE=""
|
|
17
|
-
QUERY=""
|
|
18
|
-
DAYS=180
|
|
19
|
-
LIMIT=30
|
|
20
|
-
DRY_RUN=false
|
|
21
|
-
|
|
22
|
-
while [[ $# -gt 0 ]]; do
|
|
23
|
-
case "$1" in
|
|
24
|
-
--feature) FEATURE="$2"; shift 2 ;;
|
|
25
|
-
--query) QUERY="$2"; shift 2 ;;
|
|
26
|
-
--days) DAYS="$2"; shift 2 ;;
|
|
27
|
-
--limit) LIMIT="$2"; shift 2 ;;
|
|
28
|
-
--dry-run) DRY_RUN=true; shift ;;
|
|
29
|
-
*) echo "Unknown arg: $1" >&2; exit 2 ;;
|
|
30
|
-
esac
|
|
31
|
-
done
|
|
32
|
-
|
|
33
|
-
if [[ -z "$FEATURE" ]]; then
|
|
34
|
-
echo "ERROR: --feature is required" >&2
|
|
35
|
-
exit 2
|
|
36
|
-
fi
|
|
37
|
-
if [[ -z "$QUERY" ]]; then
|
|
38
|
-
echo "ERROR: --query (search keywords) is required" >&2
|
|
39
|
-
exit 2
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
# Determine output dir
|
|
43
|
-
OUT_DIR=".vsaf/docs/features/$FEATURE"
|
|
44
|
-
|
|
45
|
-
OUT_JSON="$OUT_DIR/01-discovery-historical.json"
|
|
46
|
-
OUT_MD="$OUT_DIR/01-discovery-historical.md"
|
|
47
|
-
|
|
48
|
-
if [[ "$DRY_RUN" == "true" ]]; then
|
|
49
|
-
SPACE="${VDS_CONFLUENCE_SPACE_DEFAULT:-<VDS_CONFLUENCE_SPACE_DEFAULT>}"
|
|
50
|
-
PROJECT="${VDS_JIRA_PROJECT_DEFAULT:-<VDS_JIRA_PROJECT_DEFAULT>}"
|
|
51
|
-
CQL="space=$SPACE AND text ~ \"$QUERY\" AND lastmodified > now(\"-${DAYS}d\")"
|
|
52
|
-
JQL="project = $PROJECT AND text ~ \"$QUERY\" AND created > -${DAYS}d ORDER BY created DESC"
|
|
53
|
-
echo "DRY-RUN — would execute:"
|
|
54
|
-
echo " vds-cli confluence search --cql \"$CQL\" --limit $LIMIT --json-only"
|
|
55
|
-
echo " vds-cli jira search \"$JQL\" --limit $LIMIT --json-only"
|
|
56
|
-
echo " Write to: $OUT_JSON + $OUT_MD"
|
|
57
|
-
exit 0
|
|
58
|
-
fi
|
|
59
|
-
|
|
60
|
-
require_command vds-cli
|
|
61
|
-
|
|
62
|
-
# Ensure credentials
|
|
63
|
-
ensure_env VDS_CONFLUENCE_TOKEN "Enter VDS Confluence personal access token"
|
|
64
|
-
ensure_env VDS_JIRA_TOKEN "Enter VDS Jira personal access token"
|
|
65
|
-
ensure_env VDS_CONFLUENCE_SPACE_DEFAULT "Enter default Confluence space key (e.g. ENG)" false
|
|
66
|
-
ensure_env VDS_JIRA_PROJECT_DEFAULT "Enter default Jira project key (e.g. NTTC)" false
|
|
67
|
-
|
|
68
|
-
# Build CQL + JQL (now using real env vars)
|
|
69
|
-
CQL="space=$VDS_CONFLUENCE_SPACE_DEFAULT AND text ~ \"$QUERY\" AND lastmodified > now(\"-${DAYS}d\")"
|
|
70
|
-
JQL="project = $VDS_JIRA_PROJECT_DEFAULT AND text ~ \"$QUERY\" AND created > -${DAYS}d ORDER BY created DESC"
|
|
71
|
-
|
|
72
|
-
# Create output dir now (after dry-run exits early)
|
|
73
|
-
mkdir -p "$OUT_DIR"
|
|
74
|
-
|
|
75
|
-
# Execute searches
|
|
76
|
-
echo "Searching Confluence (limit $LIMIT, last ${DAYS}d)..."
|
|
77
|
-
CONF_RESULTS=$(vds-cli confluence search --cql "$CQL" --limit "$LIMIT" --json-only 2>/dev/null || echo '{"results":[]}')
|
|
78
|
-
|
|
79
|
-
echo "Searching Jira (limit $LIMIT, last ${DAYS}d)..."
|
|
80
|
-
JIRA_RESULTS=$(vds-cli jira search "$JQL" --limit "$LIMIT" --json-only 2>/dev/null || echo '{"issues":[]}')
|
|
81
|
-
|
|
82
|
-
# Combined JSON output + Markdown summary
|
|
83
|
-
python3 - "$CONF_RESULTS" "$JIRA_RESULTS" "$OUT_JSON" "$OUT_MD" "$QUERY" "$DAYS" <<'PYEOF'
|
|
84
|
-
import json, sys
|
|
85
|
-
conf_raw, jira_raw, out_json, out_md, query, days = sys.argv[1:7]
|
|
86
|
-
conf = json.loads(conf_raw) if conf_raw.strip() else {"results":[]}
|
|
87
|
-
jira = json.loads(jira_raw) if jira_raw.strip() else {"issues":[]}
|
|
88
|
-
|
|
89
|
-
combined = {
|
|
90
|
-
"query": query,
|
|
91
|
-
"days_back": int(days),
|
|
92
|
-
"confluence": conf.get("results", []),
|
|
93
|
-
"jira": jira.get("issues", []),
|
|
94
|
-
}
|
|
95
|
-
with open(out_json, "w") as f:
|
|
96
|
-
json.dump(combined, f, indent=2, ensure_ascii=False)
|
|
97
|
-
|
|
98
|
-
lines = [
|
|
99
|
-
f"# Discovery Historical Context — {query}",
|
|
100
|
-
f"",
|
|
101
|
-
f"> Generated by /vds-skill-search-confluence — searched last {days} days",
|
|
102
|
-
f"",
|
|
103
|
-
f"## Confluence pages ({len(combined['confluence'])} results)",
|
|
104
|
-
f"",
|
|
105
|
-
]
|
|
106
|
-
for page in combined["confluence"][:10]:
|
|
107
|
-
title = page.get("title", "<no title>")
|
|
108
|
-
url = page.get("url", page.get("_links", {}).get("webui", ""))
|
|
109
|
-
modified = page.get("lastModified", page.get("version", {}).get("when", "?"))
|
|
110
|
-
lines.append(f"- [{title}]({url}) — modified {modified}")
|
|
111
|
-
|
|
112
|
-
lines += [
|
|
113
|
-
f"",
|
|
114
|
-
f"## Jira tickets ({len(combined['jira'])} results)",
|
|
115
|
-
f"",
|
|
116
|
-
]
|
|
117
|
-
for issue in combined["jira"][:15]:
|
|
118
|
-
key = issue.get("key", "?")
|
|
119
|
-
summary = issue.get("fields", {}).get("summary", "<no summary>")
|
|
120
|
-
status = issue.get("fields", {}).get("status", {}).get("name", "?")
|
|
121
|
-
lines.append(f"- **{key}** — {summary} ({status})")
|
|
122
|
-
|
|
123
|
-
with open(out_md, "w") as f:
|
|
124
|
-
f.write("\n".join(lines) + "\n")
|
|
125
|
-
|
|
126
|
-
print(f"Wrote: {out_json}")
|
|
127
|
-
print(f"Wrote: {out_md}")
|
|
128
|
-
PYEOF
|