@agentpulselabs/cli-plugin-pulse 0.1.0 → 0.2.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/LICENSE +21 -0
- package/README.md +1 -1
- package/package.json +9 -1
- package/src/commands/pulse/gate.js +5 -3
- package/src/commands/pulse/next.js +4 -3
- package/src/commands/pulse/start.js +5 -3
- package/src/commands/pulse/status.js +4 -3
- package/src/commands/pulse/submit.js +5 -3
- package/src/commands/pulse/verify.js +7 -4
- package/src/lib/BaseCommand.js +37 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AgentPulse Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
An [oclif](https://oclif.io) plugin that adds the **`pulse`** topic — a portable, contract-enforced build
|
|
4
4
|
discipline — to the `agentpulse` CLI. It is a thin `argv → core → stdout` seam over
|
|
5
|
-
[`@agentpulselabs/pulse`](
|
|
5
|
+
[`@agentpulselabs/pulse`](https://github.com/ashishcloud/agentpulse-pulse); all discipline lives in the core.
|
|
6
6
|
|
|
7
7
|
> **Published to public npm** under the `@agentpulselabs` org (`publishConfig.access: "public"`). The CLI
|
|
8
8
|
> (`@agentpulselabs/cli`) supports plugins via `@oclif/plugin-plugins`; this plugin installs through it.
|
package/package.json
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentpulselabs/cli-plugin-pulse",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "oclif plugin that adds the `pulse` topic (portable, contract-enforced build discipline) to the agentpulse CLI. User-installed: `agentpulse plugins install @agentpulselabs/cli-plugin-pulse`. A thin argv→core seam over @agentpulselabs/pulse.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/ashishcloud/agentpulse-cli-plugin-pulse.git"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/ashishcloud/agentpulse-cli-plugin-pulse#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/ashishcloud/agentpulse-cli-plugin-pulse/issues"
|
|
17
|
+
},
|
|
10
18
|
"files": [
|
|
11
19
|
"src",
|
|
12
20
|
"README.md"
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import BaseCommand from '../../lib/BaseCommand.js';
|
|
2
3
|
import { runPulse } from '../../runPulse.js';
|
|
3
4
|
|
|
4
5
|
/** `agentpulse pulse gate` — the human-in-the-loop barrier. Advance only with --approved. */
|
|
5
|
-
export default class PulseGate extends
|
|
6
|
+
export default class PulseGate extends BaseCommand {
|
|
6
7
|
static description = 'The human gate. Advance the phase ONLY with --approved. Lock product decisions here.';
|
|
7
8
|
static examples = ['<%= config.bin %> pulse gate --approved --decisions-file decisions.json'];
|
|
8
9
|
static flags = {
|
|
@@ -18,6 +19,7 @@ export default class PulseGate extends Command {
|
|
|
18
19
|
decisions = JSON.parse(fs.readFileSync(flags['decisions-file'], 'utf8'));
|
|
19
20
|
}
|
|
20
21
|
const result = await runPulse('gate', { approved: flags.approved, decisions });
|
|
21
|
-
this.log(JSON.stringify(result, null, 2));
|
|
22
|
+
this.log(JSON.stringify(result, null, 2)); // default: raw JSON (auto-silenced under --json)
|
|
23
|
+
return result; // --json: standard envelope
|
|
22
24
|
}
|
|
23
25
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import BaseCommand from '../../lib/BaseCommand.js';
|
|
2
2
|
import { runPulse } from '../../runPulse.js';
|
|
3
3
|
|
|
4
4
|
/** `agentpulse pulse next` — emit the current phase work-list (prompts + schema, contract injected). */
|
|
5
|
-
export default class PulseNext extends
|
|
5
|
+
export default class PulseNext extends BaseCommand {
|
|
6
6
|
static description = 'Emit the current phase work-list: tasks (prompt + JSON schema) your model must run.';
|
|
7
7
|
static examples = ['<%= config.bin %> pulse next'];
|
|
8
8
|
|
|
9
9
|
async run() {
|
|
10
10
|
const result = await runPulse('next', {});
|
|
11
|
-
this.log(JSON.stringify(result, null, 2));
|
|
11
|
+
this.log(JSON.stringify(result, null, 2)); // default: raw JSON (auto-silenced under --json)
|
|
12
|
+
return result; // --json: standard envelope
|
|
12
13
|
}
|
|
13
14
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import BaseCommand from '../../lib/BaseCommand.js';
|
|
2
3
|
import { runPulse } from '../../runPulse.js';
|
|
3
4
|
|
|
4
5
|
/** `agentpulse pulse start` — begin an engagement in the current repo (.pulse/). Thin argv→core shim. */
|
|
5
|
-
export default class PulseStart extends
|
|
6
|
+
export default class PulseStart extends BaseCommand {
|
|
6
7
|
static description = 'Begin a Pulse engagement in the current repo (.pulse/).';
|
|
7
8
|
static examples = ['<%= config.bin %> pulse start --requirements "Build a widget store" --name widgets'];
|
|
8
9
|
static flags = {
|
|
@@ -19,6 +20,7 @@ export default class PulseStart extends Command {
|
|
|
19
20
|
? fs.readFileSync(flags['requirements-file'], 'utf8')
|
|
20
21
|
: (flags.requirements || '');
|
|
21
22
|
const result = await runPulse('start', { requirements, grounding: flags.grounding, name: flags.name });
|
|
22
|
-
this.log(JSON.stringify(result, null, 2));
|
|
23
|
+
this.log(JSON.stringify(result, null, 2)); // default: raw JSON (auto-silenced under --json)
|
|
24
|
+
return result; // --json: standard envelope
|
|
23
25
|
}
|
|
24
26
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import BaseCommand from '../../lib/BaseCommand.js';
|
|
2
2
|
import { runPulse } from '../../runPulse.js';
|
|
3
3
|
|
|
4
4
|
/** `agentpulse pulse status` — where does the engagement stand? Phase, contract, board progress. */
|
|
5
|
-
export default class PulseStatus extends
|
|
5
|
+
export default class PulseStatus extends BaseCommand {
|
|
6
6
|
static description = 'Show engagement status: phase, contract, board progress.';
|
|
7
7
|
static examples = ['<%= config.bin %> pulse status'];
|
|
8
8
|
|
|
9
9
|
async run() {
|
|
10
10
|
const result = await runPulse('status', {});
|
|
11
|
-
this.log(JSON.stringify(result, null, 2));
|
|
11
|
+
this.log(JSON.stringify(result, null, 2)); // default: raw JSON (auto-silenced under --json)
|
|
12
|
+
return result; // --json: standard envelope
|
|
12
13
|
}
|
|
13
14
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import BaseCommand from '../../lib/BaseCommand.js';
|
|
2
3
|
import { runPulse } from '../../runPulse.js';
|
|
3
4
|
|
|
4
5
|
/** `agentpulse pulse submit` — validate the model's structured results against schema + contract. */
|
|
5
|
-
export default class PulseSubmit extends
|
|
6
|
+
export default class PulseSubmit extends BaseCommand {
|
|
6
7
|
static description = "Submit your model's structured results (JSON). Pulse validates them vs schema + contract.";
|
|
7
8
|
static examples = ['<%= config.bin %> pulse submit --results-file discovery-results.json'];
|
|
8
9
|
static flags = {
|
|
@@ -14,6 +15,7 @@ export default class PulseSubmit extends Command {
|
|
|
14
15
|
const fs = await import('node:fs');
|
|
15
16
|
const results = JSON.parse(fs.readFileSync(flags['results-file'], 'utf8'));
|
|
16
17
|
const result = await runPulse('submit', { results });
|
|
17
|
-
this.log(JSON.stringify(result, null, 2));
|
|
18
|
+
this.log(JSON.stringify(result, null, 2)); // default: raw JSON (auto-silenced under --json)
|
|
19
|
+
return result; // --json: standard envelope
|
|
18
20
|
}
|
|
19
21
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import BaseCommand from '../../lib/BaseCommand.js';
|
|
2
3
|
import { runPulse } from '../../runPulse.js';
|
|
3
4
|
|
|
4
5
|
/** `agentpulse pulse verify` — run the contract's deterministic gate command. "Done" is this exit code. */
|
|
5
|
-
export default class PulseVerify extends
|
|
6
|
+
export default class PulseVerify extends BaseCommand {
|
|
6
7
|
static description = "Run the contract's gate command (e.g. `npm run check`) and report pass/fail. Never an LLM opinion.";
|
|
7
8
|
static examples = ['<%= config.bin %> pulse verify'];
|
|
8
9
|
static flags = {
|
|
@@ -12,7 +13,9 @@ export default class PulseVerify extends Command {
|
|
|
12
13
|
async run() {
|
|
13
14
|
const { flags } = await this.parse(PulseVerify);
|
|
14
15
|
const result = await runPulse('verify', { cwd: flags.cwd });
|
|
15
|
-
this.log(JSON.stringify(result, null, 2));
|
|
16
|
-
|
|
16
|
+
this.log(JSON.stringify(result, null, 2)); // default: raw JSON (auto-silenced under --json)
|
|
17
|
+
// A red gate is a SUCCESSFUL run reporting ok:false + exit 1 (so CI/scripts gate on it) — not a thrown error.
|
|
18
|
+
if (!result.green) return this.problem(result, 1);
|
|
19
|
+
return result; // --json: standard envelope
|
|
17
20
|
}
|
|
18
21
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* BaseCommand — the pulse plugin's half of the machine-readable CLI contract (docs/PLAN.md M0), matching the host
|
|
5
|
+
* CLI's BaseCommand so `agentpulse pulse <verb> --json` yields the SAME standard envelope as first-party commands:
|
|
6
|
+
*
|
|
7
|
+
* success: { tool:'agentpulse', command:'pulse status', version, ok:true, result }
|
|
8
|
+
* error: { tool:'agentpulse', command:'pulse status', version, ok:false, error:{ code, message } }
|
|
9
|
+
*
|
|
10
|
+
* Behavior note (deliberate, back-compat): pulse output is machine-oriented (work-lists with prompts + JSON
|
|
11
|
+
* schemas an agent consumes), so the DEFAULT (no --json) still prints the raw engine result as pretty JSON —
|
|
12
|
+
* exactly as before. `--json` layers the standard envelope on top. Both are JSON; --json is the stable contract.
|
|
13
|
+
*/
|
|
14
|
+
export default class BaseCommand extends Command {
|
|
15
|
+
static enableJsonFlag = true;
|
|
16
|
+
|
|
17
|
+
toSuccessJson(result) {
|
|
18
|
+
const marked = result && typeof result === 'object' && result.__ap === true;
|
|
19
|
+
const ok = marked ? result.ok : true;
|
|
20
|
+
const payload = marked ? result.result : result;
|
|
21
|
+
return { tool: 'agentpulse', command: this.commandName(), version: this.config?.version, ok, result: payload };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
toErrorJson(err) {
|
|
25
|
+
return {
|
|
26
|
+
tool: 'agentpulse', command: this.commandName(), version: this.config?.version, ok: false,
|
|
27
|
+
error: { code: (err && err.code) || 'E_ERROR', message: (err && err.message) || String(err) },
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
commandName() { return String(this.id || this.ctor?.id || '').replace(/:/g, ' '); }
|
|
32
|
+
|
|
33
|
+
fail(code, message, exit = 1) { process.exitCode = exit; this.error(message, { code, exit }); }
|
|
34
|
+
|
|
35
|
+
/** A successful run that reports ok:false and exits non-zero, carrying its full payload (e.g. `verify` red). */
|
|
36
|
+
problem(payload, exit = 1) { process.exitCode = exit; return { __ap: true, ok: false, result: payload }; }
|
|
37
|
+
}
|