@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.1",
4
- "description": "JengaAgent — agentic project management CLI",
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-Deploy Manual Steps
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