@jenga-ai/agent 1.2.1 → 1.2.2
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jenga-ai/agent",
|
|
3
|
-
"version": "1.2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.2",
|
|
4
|
+
"description": "Structured multi-agent development workflow for AI coding agents — scrum board, role-bounded scrum master / developer / tester agents, and 30+ slash-command skills. Works with Claude Code, GitHub Copilot, and Codex.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -9,8 +9,12 @@
|
|
|
9
9
|
"bin": {
|
|
10
10
|
"jenga": "./bin/jenga.js"
|
|
11
11
|
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=14.13.1"
|
|
14
|
+
},
|
|
12
15
|
"scripts": {
|
|
13
16
|
"postinstall": "node scripts/postinstall.js",
|
|
17
|
+
"validate:npm-metadata": "bash scripts/validate_npm_metadata.sh",
|
|
14
18
|
"ui:dev": "npm run ui:dev --prefix project/app",
|
|
15
19
|
"ui:build": "npm run ui:build --prefix project/app",
|
|
16
20
|
"api:start": "npm run api:start --prefix project/app",
|
|
@@ -32,10 +36,35 @@
|
|
|
32
36
|
],
|
|
33
37
|
"repository": {
|
|
34
38
|
"type": "git",
|
|
35
|
-
"url": "https://github.com/samwelmunga/jenga-npm"
|
|
39
|
+
"url": "git+https://github.com/samwelmunga/jenga-npm.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/samwelmunga/jenga-npm#readme",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/samwelmunga/jenga-npm/issues"
|
|
44
|
+
},
|
|
45
|
+
"keywords": [
|
|
46
|
+
"ai-agents",
|
|
47
|
+
"agentic",
|
|
48
|
+
"agentic-workflow",
|
|
49
|
+
"multi-agent",
|
|
50
|
+
"agent-framework",
|
|
51
|
+
"ai-development",
|
|
52
|
+
"claude",
|
|
53
|
+
"claude-code",
|
|
54
|
+
"agents-md",
|
|
55
|
+
"copilot",
|
|
56
|
+
"github-copilot",
|
|
57
|
+
"codex",
|
|
58
|
+
"skills",
|
|
59
|
+
"project-management",
|
|
60
|
+
"developer-tools",
|
|
61
|
+
"cli"
|
|
62
|
+
],
|
|
63
|
+
"author": {
|
|
64
|
+
"name": "Samwel Munga",
|
|
65
|
+
"email": "samwelmunga88@hotmail.se",
|
|
66
|
+
"url": "https://knappkod.se/jenga-ai"
|
|
36
67
|
},
|
|
37
|
-
"keywords": [],
|
|
38
|
-
"author": "",
|
|
39
68
|
"license": "MIT",
|
|
40
69
|
"dependencies": {
|
|
41
70
|
"@huggingface/transformers": "^4.2.0"
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# validate_npm_metadata.sh — deterministic check that package.json carries
|
|
4
|
+
# the metadata npm/GitHub discovery depends on (E41_S01_T02).
|
|
5
|
+
#
|
|
6
|
+
# Rationale: per the repo's "Scripts Over Inline Logic" principle
|
|
7
|
+
# (CLAUDE.md), this is a script rather than an agent instruction so that
|
|
8
|
+
# future drift in package.json's publish-facing fields (e.g. keywords
|
|
9
|
+
# accidentally cleared, or repository.url silently re-pointed at the
|
|
10
|
+
# private samwelmunga/JengaAgent repo instead of the public jenga-npm
|
|
11
|
+
# mirror) is caught deterministically instead of relying on an agent
|
|
12
|
+
# noticing during review.
|
|
13
|
+
#
|
|
14
|
+
# IMPORTANT — no pinned version check:
|
|
15
|
+
# This script intentionally does NOT compare package.json's `version`
|
|
16
|
+
# field against any hardcoded literal. E41_S01_T01 established that the
|
|
17
|
+
# locally committed version and the version actually published to npm
|
|
18
|
+
# drift independently over time, so pinning a literal here would go
|
|
19
|
+
# stale on the very next release. If a version check is wanted at all,
|
|
20
|
+
# it is structural only (present + semver-shaped), never a pinned value.
|
|
21
|
+
#
|
|
22
|
+
# Usage:
|
|
23
|
+
# bash scripts/validate_npm_metadata.sh
|
|
24
|
+
# npm run validate:npm-metadata
|
|
25
|
+
#
|
|
26
|
+
# Exit codes:
|
|
27
|
+
# 0 All checks passed.
|
|
28
|
+
# 1 One or more checks failed (each failure is printed with a
|
|
29
|
+
# descriptive message; a summary count follows).
|
|
30
|
+
#
|
|
31
|
+
# Dependencies: node only (already a required runtime for this project —
|
|
32
|
+
# see package.json's "engines" field). No new dependency is introduced.
|
|
33
|
+
|
|
34
|
+
set -euo pipefail
|
|
35
|
+
|
|
36
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
37
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
38
|
+
PACKAGE_JSON="${1:-$REPO_ROOT/package.json}"
|
|
39
|
+
|
|
40
|
+
if [[ ! -f "$PACKAGE_JSON" ]]; then
|
|
41
|
+
echo "FAIL: package.json not found at $PACKAGE_JSON" >&2
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# All validation logic lives in one embedded Node script to avoid the
|
|
46
|
+
# quoting/escaping pitfalls of parsing JSON arrays and nested objects from
|
|
47
|
+
# bash. Node prints one "PASS: ..." or "FAIL: ..." line per check to
|
|
48
|
+
# stdout, plus a final "SUMMARY: <n> failed" line. Bash only interprets
|
|
49
|
+
# the final summary line to decide the exit code and print the banner.
|
|
50
|
+
NODE_OUTPUT="$(node -e '
|
|
51
|
+
const fs = require("fs");
|
|
52
|
+
|
|
53
|
+
const pkgPath = process.argv[1];
|
|
54
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
55
|
+
|
|
56
|
+
const failures = [];
|
|
57
|
+
const pass = (msg) => console.log("PASS: " + msg);
|
|
58
|
+
const fail = (msg) => { failures.push(msg); console.log("FAIL: " + msg); };
|
|
59
|
+
|
|
60
|
+
// keywords: must exist, be a non-empty array
|
|
61
|
+
if (!Array.isArray(pkg.keywords) || pkg.keywords.length === 0) {
|
|
62
|
+
fail("keywords is empty or missing — package.json must declare a non-empty keywords array for npm/GitHub discoverability.");
|
|
63
|
+
} else {
|
|
64
|
+
pass("keywords is present with " + pkg.keywords.length + " entries.");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// author: must exist and be non-empty (string or object form)
|
|
68
|
+
const authorEmpty = (() => {
|
|
69
|
+
if (pkg.author == null) return true;
|
|
70
|
+
if (typeof pkg.author === "string") return pkg.author.trim().length === 0;
|
|
71
|
+
if (typeof pkg.author === "object") {
|
|
72
|
+
return !pkg.author.name || String(pkg.author.name).trim().length === 0;
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
})();
|
|
76
|
+
if (authorEmpty) {
|
|
77
|
+
fail("author is empty or missing — package.json must declare an author (string or {name, ...} object).");
|
|
78
|
+
} else {
|
|
79
|
+
pass("author is present.");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// repository / homepage / bugs: must all be present
|
|
83
|
+
if (pkg.repository == null || (typeof pkg.repository === "object" && Object.keys(pkg.repository).length === 0)) {
|
|
84
|
+
fail("repository is missing from package.json.");
|
|
85
|
+
} else {
|
|
86
|
+
pass("repository is present.");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!pkg.homepage || String(pkg.homepage).trim().length === 0) {
|
|
90
|
+
fail("homepage is missing from package.json.");
|
|
91
|
+
} else {
|
|
92
|
+
pass("homepage is present.");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (pkg.bugs == null || (typeof pkg.bugs === "object" && Object.keys(pkg.bugs).length === 0)) {
|
|
96
|
+
fail("bugs is missing from package.json.");
|
|
97
|
+
} else {
|
|
98
|
+
pass("bugs is present.");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// repository.url (object form) or repository (string form) must point at
|
|
102
|
+
// the PUBLIC mirror (samwelmunga/jenga-npm), never the private repo.
|
|
103
|
+
const PUBLIC_REPO_MARKER = "samwelmunga/jenga-npm";
|
|
104
|
+
if (pkg.repository != null) {
|
|
105
|
+
const repoUrl = typeof pkg.repository === "string"
|
|
106
|
+
? pkg.repository
|
|
107
|
+
: (pkg.repository.url || "");
|
|
108
|
+
|
|
109
|
+
if (!repoUrl || repoUrl.trim().length === 0) {
|
|
110
|
+
fail("repository is present but has no resolvable url.");
|
|
111
|
+
} else if (!repoUrl.includes(PUBLIC_REPO_MARKER)) {
|
|
112
|
+
fail("repository.url (\"" + repoUrl + "\") does not point at the public " + PUBLIC_REPO_MARKER + " repo — it must not reference a private repo (e.g. samwelmunga/JengaAgent) or any other location.");
|
|
113
|
+
} else {
|
|
114
|
+
pass("repository.url points at the public " + PUBLIC_REPO_MARKER + " repo.");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// version: structural semver check only — NEVER a pinned literal value.
|
|
119
|
+
// See header comment for why a pinned check would go stale immediately.
|
|
120
|
+
const SEMVER_RE = /^\d+\.\d+\.\d+/;
|
|
121
|
+
if (!pkg.version || !SEMVER_RE.test(String(pkg.version))) {
|
|
122
|
+
fail("version (\"" + pkg.version + "\") is missing or not a valid semver-shaped string.");
|
|
123
|
+
} else {
|
|
124
|
+
pass("version (\"" + pkg.version + "\") is a valid semver-shaped string (no pinned-value check performed, by design).");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log("SUMMARY: " + failures.length + " failed");
|
|
128
|
+
process.exit(failures.length > 0 ? 1 : 0);
|
|
129
|
+
' "$PACKAGE_JSON")" && NODE_EXIT=0 || NODE_EXIT=$?
|
|
130
|
+
|
|
131
|
+
echo "$NODE_OUTPUT"
|
|
132
|
+
echo
|
|
133
|
+
|
|
134
|
+
FAILED_COUNT="$(echo "$NODE_OUTPUT" | grep -c '^FAIL:' || true)"
|
|
135
|
+
|
|
136
|
+
if [[ "$NODE_EXIT" -ne 0 || "$FAILED_COUNT" -gt 0 ]]; then
|
|
137
|
+
echo "npm publish metadata validation FAILED ($FAILED_COUNT check(s) failed). See FAIL lines above." >&2
|
|
138
|
+
exit 1
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
echo "All npm publish metadata checks passed."
|
|
142
|
+
exit 0
|
|
@@ -190,7 +190,7 @@ A successful non-dry-run produces:
|
|
|
190
190
|
- A history entry in `project/logs/publish-history.json` written by
|
|
191
191
|
`publish_deploy.sh` with `platform_state: "triggered"`
|
|
192
192
|
|
|
193
|
-
## Post-
|
|
193
|
+
## Post-deploy manual steps
|
|
194
194
|
|
|
195
195
|
After a successful deploy trigger, the adapter prints the workflow run URL.
|
|
196
196
|
The operator should:
|
|
@@ -465,9 +465,18 @@ print_manual_steps() {
|
|
|
465
465
|
droplet)
|
|
466
466
|
adapter_doc="$PUBLISH_REPO_ROOT/skills/publish/adapters/droplet.md"
|
|
467
467
|
;;
|
|
468
|
-
|
|
468
|
+
npm)
|
|
469
|
+
adapter_doc="$PUBLISH_REPO_ROOT/skills/publish/adapters/npm.md"
|
|
470
|
+
;;
|
|
471
|
+
npm-ci)
|
|
472
|
+
adapter_doc="$PUBLISH_REPO_ROOT/skills/publish/adapters/npm-ci.md"
|
|
473
|
+
;;
|
|
474
|
+
mobile-ios)
|
|
469
475
|
adapter_doc="$PUBLISH_REPO_ROOT/skills/publish/adapters/mobile-ios.md"
|
|
470
476
|
;;
|
|
477
|
+
*)
|
|
478
|
+
return 0
|
|
479
|
+
;;
|
|
471
480
|
esac
|
|
472
481
|
[[ -f "$adapter_doc" ]] || return 0
|
|
473
482
|
local manual_steps
|