software-defence-factory 0.10.0 → 0.11.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.
@@ -1,6 +1,6 @@
1
1
  # Factory skills
2
2
 
3
- These six original, portable skills are project-local Markdown. They require no AIOS installation. A harness must discover `.agents/skills` or receive the selected SKILL.md explicitly. The export command `node scripts/export-kit.mjs NEW_OUTPUT_DIRECTORY` stages these skills with the portable adoption kit. Copy the needed folders into a target repository under its own accepted instructions before dispatch. Do not overwrite its AGENTS.md.
3
+ These six original, portable skills are project-local Markdown. A harness must discover `.agents/skills` or receive the selected SKILL.md explicitly. The export command `node scripts/export-kit.mjs NEW_OUTPUT_DIRECTORY` stages these skills with the portable adoption kit. Copy the needed folders into a target repository under its own accepted instructions before dispatch. Do not overwrite its AGENTS.md.
4
4
 
5
5
  - [factory-triage](factory-triage/SKILL.md): Turn an incoming factory issue into a bounded disposition and capability request. Use before specification or implementation starts.
6
6
  - [factory-spec](factory-spec/SKILL.md): Write an implementable factory task with observable acceptance criteria, required capabilities and a bounded verification plan.
package/README.md CHANGED
@@ -1,27 +1,35 @@
1
- # Software & Defence Factory
1
+ # Factory
2
2
 
3
3
  A portable method and a local runtime for taking a scoped software task through implementation, checks, independent review and an explicit handoff.
4
4
 
5
- Developed by [Arcitai](https://github.com/arcitai). The CLI is **software-defence-factory**. It works with existing repositories, Codex, Pi or a configured executor. No personal context system is required.
5
+ Published by [Arcitai](https://github.com/arcitai). Invoke **factory** with your existing repositories, Codex, Pi or a configured executor. The npm package remains **software-defence-factory**; the compatibility executable `software-defence-factory` uses the same implementation, state and updater.
6
6
 
7
7
  ## Start here
8
8
 
9
9
  Install the published [npm package](https://www.npmjs.com/package/software-defence-factory). The CLI includes the dashboard; no source checkout is needed.
10
10
 
11
11
  ```sh
12
- npm install --global software-defence-factory
13
- software-defence-factory help
12
+ npm install --global software-defence-factory@latest
13
+ factory help
14
14
  ```
15
15
 
16
- For occasional use: `npx software-defence-factory@latest help`.
16
+ For occasional use: `npm exec --package=software-defence-factory@latest -- factory help`.
17
+
18
+ Starting with 0.11.1, the package provides both executable names. To upgrade an
19
+ older global installation, run
20
+ `npm install --global software-defence-factory@latest` to expose the new `factory`
21
+ executable. Private cached updates keep the old command working but do not add
22
+ global symlinks. Check `command -v factory` first; if it belongs to another tool,
23
+ keep the compatibility command or use the explicit `npm exec` invocation above.
24
+ Do not overwrite it with `--force`. See [installation compatibility](docs/npm.md).
17
25
 
18
26
  Choose the part you need:
19
27
 
20
28
  | Outcome | Command / guide |
21
29
  | --- | --- |
22
30
  | Set up an operator, worker and application | [Setup plan and acceptance checklist](docs/setup.md) |
23
- | Use the method with your existing agent | `software-defence-factory kit --output ./factory-kit` — exports a new staging directory |
24
- | Try the runtime without inference | `software-defence-factory demo` — Docker required; synthetic sample only |
31
+ | Use the method with your existing agent | `factory kit --output ./factory-kit` — exports a new staging directory |
32
+ | Try the runtime without inference | `factory demo` — Docker required; synthetic sample only |
25
33
  | Connect an existing repository | [Runtime quickstart](docs/quickstart.md) |
26
34
  | Understand installation and updates | [npm and npx](docs/npm.md) |
27
35
  | Restore a dashboard after boot or reconnect remotely | [Services and SSH tunnels](docs/services.md) |
@@ -37,11 +45,11 @@ The runtime supplies policy and six focused skills to its isolated jobs. `init`
37
45
 
38
46
  Each result belongs to a specific candidate commit and policy. A failed check blocks delivery. Changing the candidate or check policy invalidates earlier evidence. Approval records a handoff; publishing, merging and deployment follow the application's separate authority.
39
47
 
40
- The project dashboard has an **Inbox**, measured **Analytics**, **Agents**, **Skills**, **Automations**, **Definition** and **Infrastructure**. New issue offers the repository’s issue templates, a blank local form or a selectable GitHub issue. Create an issue on the supported repository provider, then choose Start work separately; local brief execution remains available. CLI `issue` exposes the same intake. Definition lives with settings above the theme control. The CLI reads the same definition and controller state. Agent roles use a selected harness such as Codex or Pi; a worker executes their isolated jobs on a host. See [concepts](docs/concepts.md) and [supported interfaces](docs/interfaces.md). Optional automations belong to the selected harness, which calls Factory CLI/API. Factory runs no cron scheduler. See [provider boundaries](docs/integrations.md).
48
+ The project dashboard has an **Inbox**, measured **Analytics**, **Agents**, **Skills**, **Automations**, **Definition** and **Infrastructure**. Inbox lists repository issues with readiness and linked execution attempts. New issue offers repository templates or a blank creation form. Create an issue on the supported repository provider, then choose Start work separately; local brief execution remains available. CLI `issue` exposes the same intake. Definition lives with settings above the theme control. The CLI reads the same definition and controller state. Agent roles use a selected harness such as Codex or Pi; a worker executes their isolated jobs on a host. See [concepts](docs/concepts.md) and [supported interfaces](docs/interfaces.md). Optional automations belong to the selected harness, which calls Factory CLI/API. Factory runs no cron scheduler. See [provider boundaries](docs/integrations.md).
41
49
 
42
50
  The optional **defence** workflow accepts scoped incident evidence and produces a private, read-only draft. It does not monitor production or claim verified recovery. See [defence integration](docs/defence-integration.md).
43
51
 
44
- Start setup with `software-defence-factory foundation` and the [Factory Foundation plan](docs/setup.md). No AIOS installation is required.
52
+ Start setup with `factory foundation` and the [Factory Foundation plan](docs/setup.md).
45
53
 
46
54
  ## Repository map
47
55
 
@@ -55,8 +63,6 @@ Start setup with `software-defence-factory foundation` and the [Factory Foundati
55
63
  | `scripts/`, `tests/` | Packaging, qualification, release checks and behavioral tests |
56
64
  | `docs/` | Setup, architecture, recovery, proof and ownership |
57
65
 
58
- The current runtime replaces earlier prototypes. Their source and research remain in Git history; they are not part of the installed package.
59
-
60
66
  ## Contributing
61
67
 
62
68
  Requires Node 22.13+, npm and Git. Docker is needed only for integration qualification.
@@ -6,7 +6,7 @@ import { spawn } from 'node:child_process';
6
6
  import { createServer } from 'node:net';
7
7
  import { ROOT, PINS, DEFAULT_STATE, configAt, save, json, run, stream, digest, api, sleep, stopContainers, PUBLICATION_API_TIMEOUT_MS } from '../factory/lib.mjs';
8
8
  import { assertInstalledJobImage, installCustomJobImage, installStandardJobImage, inspectImageInstallation } from '../factory/image-install.mjs';
9
- import { listIssues, readIssue } from '../factory/issue-intake.mjs';
9
+ import { readIssue } from '../factory/issue-intake.mjs';
10
10
  import { recommendWork } from '../factory/intake.mjs';
11
11
  import { factoryDefinition, foundationSkill } from '../factory/definition.mjs';
12
12
  import { harnessOf } from '../factory/lib.mjs';
@@ -55,6 +55,16 @@ function init(repo, harness='codex', check='', port=7331, sourceRef='HEAD', deli
55
55
  console.log(`Configured ${state}\nApp files were not changed. Only committed code is cloned into jobs.`);
56
56
  }
57
57
 
58
+ async function listInbox(defaultSource) {
59
+ const source=flags.source || defaultSource;
60
+ if(!['factory','inbox','remote','github'].includes(source))throw new Error('Choose --source factory, inbox or remote');
61
+ if(source==='factory') {
62
+ if(flags.page !== undefined || flags['issue-state'] !== undefined)throw new Error('Repository paging/state filters require --source inbox or remote.');
63
+ return (await api(state,'/api/v1/status')).jobs;
64
+ }
65
+ return api(state,`/api/v1/issues?page=${encodeURIComponent(flags.page || 1)}&state=${encodeURIComponent(flags['issue-state'] || 'open')}`);
66
+ }
67
+
58
68
  async function install() {
59
69
  const config=configAt(state);
60
70
  if (!['darwin','linux'].includes(process.platform)||!['arm64','x64'].includes(process.arch)) throw new Error('Use macOS/Linux arm64/amd64, or WSL2');
@@ -101,10 +111,10 @@ async function stop() {
101
111
  }
102
112
  stopContainers(state);console.log('Controller and its labelled containers stopped.');
103
113
  }
104
- async function submit(workflow,spec,sourceRef=flags['source-ref']) {
114
+ async function submit(workflow,spec,sourceRef=flags['source-ref'],sourceURL) {
105
115
  if(Buffer.byteLength(spec)>240000)throw new Error('Task exceeds 240 KB');
106
116
  const title=workflow==='defence'?'Private incident triage':spec.split('\n').find(s=>s.trim())?.replace(/^#+\s*/, '').slice(0,100)||'Software task';
107
- return api(state,'/api/v1/jobs',{workflow,repository:'app',spec,title,...(sourceRef===undefined?{}:{source_ref:sourceRef})});
117
+ return api(state,'/api/v1/jobs',{workflow,repository:'app',spec,title,...(sourceURL?{source_url:sourceURL}:{}),...(sourceRef===undefined?{}:{source_ref:sourceRef})});
108
118
  }
109
119
  async function jobAction(action) {
110
120
  const id=positional[0];if(!/^job_[a-z0-9]+$/.test(id || ''))throw new Error('A job ID is required');
@@ -157,6 +167,7 @@ async function abandonDeliveryJob(jobId) {
157
167
  }
158
168
 
159
169
  try {
170
+ if(flags['brief-file'] !== undefined && (command !== 'issue' || positional[0] !== 'start' || !(flags.url || flags.github) || flags.file || flags.draft))throw new Error('Use --brief-file only with issue start --url (or --github); local --file/--draft already supplies the scope.');
160
171
  if(command==='init') {
161
172
  if(!flags.repo)throw new Error('init requires --repo /path/to/existing/git/repo');
162
173
  if(flags.harness && flags.agent && flags.harness !== flags.agent)throw new Error('--harness conflicts with legacy --agent');
@@ -191,9 +202,10 @@ try {
191
202
  const value=command==='agents'?definition.agents:command==='skills'?{agents:definition.skills,operators:definition.operator_skills}:definition;
192
203
  console.log(JSON.stringify(value,null,2));
193
204
  }
194
- else if(['infrastructure','automations','inbox'].includes(command)) {
205
+ else if(command==='inbox')console.log(JSON.stringify(await listInbox('inbox'),null,2));
206
+ else if(['infrastructure','automations'].includes(command)) {
195
207
  const snapshot=await api(state,'/api/v1/status');
196
- console.log(JSON.stringify(command==='inbox'?snapshot.jobs:command==='automations'?snapshot.automation_control:snapshot[command],null,2));
208
+ console.log(JSON.stringify(command==='automations'?snapshot.automation_control:snapshot[command],null,2));
197
209
  }
198
210
  else if(command==='status') { const snapshot=await api(state,'/api/v1/status');delete snapshot.csrf_token;console.log(JSON.stringify(snapshot,null,2)); }
199
211
  else if(command==='doctor') {
@@ -204,8 +216,7 @@ try {
204
216
  } else if(command==='issue') {
205
217
  const action=positional[0], sourceURL=flags.url || flags.github;
206
218
  if(action==='list') {
207
- if(flags.source && !['factory','remote','github'].includes(flags.source))throw new Error('Choose --source factory or remote');
208
- console.log(JSON.stringify(['github','remote'].includes(flags.source) ? await api(state,`/api/v1/issues?page=${encodeURIComponent(flags.page || 1)}`) : (await api(state,'/api/v1/status')).jobs,null,2));
219
+ console.log(JSON.stringify(await listInbox('factory'),null,2));
209
220
  } else if(action==='templates') console.log(JSON.stringify(await api(state,'/api/v1/issue-templates'),null,2));
210
221
  else if(action==='connection') console.log(JSON.stringify(await api(state,'/api/v1/issue-connection'),null,2));
211
222
  else if(action==='submissions') console.log(JSON.stringify(await api(state,'/api/v1/issue-submissions'),null,2));
@@ -233,17 +244,21 @@ try {
233
244
  } else if(action==='start') {
234
245
  if(!['software','defence'].includes(flags.workflow))throw new Error('Review the issue and choose --workflow software or defence');
235
246
  if([flags.file,sourceURL,flags.draft].filter(Boolean).length!==1)throw new Error('Choose --file brief.md, --draft draft.json or --url ISSUE_URL');
236
- let input;
237
- if(sourceURL) { const issue=await api(state,'/api/v1/issues/preview',{url:sourceURL});input={title:issue.title,spec:issue.spec,source_url:issue.url}; }
247
+ let input, brief;
248
+ if(flags['brief-file'] !== undefined) {
249
+ brief=readFileSync(resolve(flags['brief-file']),'utf8');
250
+ if(brief.length>16000)throw new Error('Operator brief must be at most 16000 characters.');
251
+ }
252
+ if(sourceURL) { const issue=await api(state,'/api/v1/issues/preview',{url:sourceURL});input={title:issue.title,url:issue.url,expected_spec:issue.spec,...(brief===undefined?{}:{brief})}; }
238
253
  else if(flags.draft) { const draft=json(resolve(flags.draft));input={title:draft.title,spec:draft.spec}; }
239
254
  else input={title:flags.title,spec:readFileSync(resolve(flags.file),'utf8')};
240
255
  input.title=flags.title || input.title;
241
- if(typeof input.title!=='string'||!input.title.trim()||input.title.length>160)throw new Error('Provide a title of 1–160 characters (use --title for a blank issue)');
256
+ if(!sourceURL && (typeof input.title!=='string'||!input.title.trim()||input.title.length>160))throw new Error('Provide a title of 1–160 characters (use --title for a blank issue)');
242
257
  if(flags.workflow==='software'&&!configAt(state).check?.trim())throw new Error('Configure an app check before submitting software work');
243
- console.log(JSON.stringify(await api(state,'/api/v1/jobs',{...input,workflow:flags.workflow,repository:'app',model:flags.model || '',...(flags['source-ref']===undefined?{}:{source_ref:flags['source-ref']})}),null,2));
258
+ console.log(JSON.stringify(await api(state,sourceURL ? '/api/v1/issues/start' : '/api/v1/jobs',{...input,workflow:flags.workflow,repository:'app',model:flags.model || '',...(flags['source-ref']===undefined?{}:{source_ref:flags['source-ref']})}),null,2));
244
259
  } else throw new Error('Use issue list|connection|templates|preview|recommend|draft|create|start|submissions|recover; see help');
245
260
  } else if(command==='issues') {
246
- console.log(JSON.stringify(await listIssues(configAt(state).repo,Number(flags.page || 1)),null,2));
261
+ console.log(JSON.stringify(await listInbox('inbox'),null,2));
247
262
  } else if(command==='recommend') {
248
263
  if(Boolean(flags.issue) === Boolean(flags.file))throw new Error('Choose --file task.md or --issue URL');
249
264
  const recommendation=flags.issue ? (await readIssue(configAt(state).repo,flags.issue)).recommendation : recommendWork({spec:readFileSync(resolve(flags.file),'utf8')});
@@ -251,13 +266,13 @@ try {
251
266
  } else if(command==='run') {
252
267
  const workflow=flags.workflow || 'software';
253
268
  if(!['software','defence'].includes(workflow))throw new Error('Choose --workflow software or defence');
254
- let spec;
269
+ let spec,sourceURL;
255
270
  if(flags.issue) {
256
- spec=(await readIssue(configAt(state).repo,flags.issue)).spec;
271
+ const issue=await readIssue(configAt(state).repo,flags.issue);spec=issue.spec;sourceURL=issue.url;
257
272
  } else if(flags.file)spec=readFileSync(resolve(flags.file),'utf8');
258
273
  else throw new Error('Use --file task.md or --issue https://github.com/owner/repo/issues/123');
259
274
  if(workflow==='software'&&!configAt(state).check?.trim())throw new Error('Configure an app check before submitting software work');
260
- console.log(JSON.stringify(await submit(workflow,spec)));
275
+ console.log(JSON.stringify(await submit(workflow,spec,flags['source-ref'],sourceURL)));
261
276
  } else if(command==='incident') {
262
277
  if(!flags.file)throw new Error('Use --file incident.json; see factory/examples/incident.json');
263
278
  console.log(JSON.stringify(await admitIncident(state,json(resolve(flags.file)),submit)));
@@ -289,7 +304,10 @@ try {
289
304
  } else if(command==='kit') {
290
305
  if(!flags.output)throw new Error('kit requires --output NEW_DIRECTORY');
291
306
  await stream(process.execPath,[join(ROOT,'scripts/export-kit.mjs'),resolve(flags.output)]);
292
- } else if(['help','--help','-h'].includes(command))console.log(`Software & Defence Factory ${VERSION} (test release)
307
+ } else if(['help','--help','-h'].includes(command))console.log(`Factory ${VERSION} (test release)
308
+
309
+ Usage: factory <command> [options]
310
+ Compatibility executable: software-defence-factory (same runtime and state)
293
311
 
294
312
  kit --output NEW_DIRECTORY Export the portable method without a runtime
295
313
  demo Install and run a synthetic sample (no model key)
@@ -303,7 +321,9 @@ try {
303
321
  web probe --state PATH Execute the pinned local Chromium readiness probe
304
322
  foundation Read the operator setup skill; no installation required
305
323
  definition | agents | skills Inspect roles, instructions and installation settings
306
- inbox | infrastructure | automations Inspect live tasks, host/worker and automation state
324
+ inbox [--page N] [--issue-state open|closed|all] [--source inbox|factory]
325
+ Repository backlog (default); factory: execution-only array
326
+ infrastructure | automations Inspect host/worker and automation state
307
327
  workflows Compatibility alias for definition
308
328
  --agent Legacy alias for init --harness
309
329
  serve Foreground supervisor
@@ -316,7 +336,8 @@ try {
316
336
  service resume Release a reconciled maintenance reservation
317
337
  tunnel install|start|stop|status|logs|uninstall --host SSH_ALIAS --port PORT
318
338
  Persistent loopback SSH tunnel (macOS/Linux)
319
- issue list [--source remote] [--page N] List local executions or open repository issues
339
+ issue list [--source inbox|remote|factory] [--page N] [--issue-state open|closed|all]
340
+ List linked repository issues or local executions (default)
320
341
  issue templates Read this repository's issue forms and contact links
321
342
  issue preview --url URL Preview one repository issue without starting work
322
343
  issue recommend --file brief.md | --url URL
@@ -328,8 +349,9 @@ try {
328
349
  issue recover --key REQUEST_ID Reconcile an uncertain creation without another write
329
350
  issue start --draft draft.json | --url URL | --file brief.md --title TITLE
330
351
  --workflow software|defence [--source-ref REF] [--model MODEL]
331
- Create a local issue and start work; no GitHub write
332
- issues [--page N] Browse open project issues, with next_page for more
352
+ [--brief-file operator.md] Only with --url; at most 16000 characters
353
+ Explicitly start execution; no GitHub write
354
+ issues [--page N] Browse linked project issues; supports --issue-state
333
355
  recommend --file task.md | --issue URL Suggest a work type without starting work
334
356
  run --file task.md | --issue URL Submit software (default), or --workflow defence
335
357
  [--source-ref REF] Pin a configured-repository ref before admission
@@ -3,7 +3,7 @@
3
3
  The optional defence workflow receives a bounded incident record through:
4
4
 
5
5
  ```sh
6
- software-defence-factory incident --file /private/path/incident.json --state /private/state/my-app
6
+ factory incident --file /private/path/incident.json --state /private/state/my-app
7
7
  ```
8
8
 
9
9
  Use factory/examples/incident.json as the input schema example. Intake validates scope and evidence, records a digest and deduplicates the event identity. Evidence and reports remain in the private installation. Do not place customer findings in public issues or source control.
@@ -9,9 +9,10 @@ shell endpoint or a second scheduler.
9
9
 
10
10
  | Capability | CLI | Shared API | Dashboard | Remaining work |
11
11
  | --- | --- | --- | --- | --- |
12
- | Project/queue/attempt state | `status`, `inbox` JSON | `GET /api/v1/status` | Project, tasks, details/history | Stable versioned agent result/error contract |
13
- | Start local work | `issue start --file --title`, `--draft` or `--url`, explicit `--workflow`, optional `--model` | `POST /api/v1/jobs` | Local execution only → review → Create & start locally | Persistent unstarted drafts and typed incident intake remain separate |
14
- | Browse/import repository issues | `issue list --source remote [--page N]`, `issue preview --url URL` via controller provider | Authenticated `GET /api/v1/issues`, `POST /api/v1/issues/preview` using shared readers | Paged open-issue list, search loaded results, preview and explicit start for either type | Issue → execution links retained; no implicit polling |
12
+ | Project/queue/attempt state | `status`, `inbox --source factory` JSON | `GET /api/v1/status` | Project, tasks, details/history | Stable versioned agent result/error contract |
13
+ | Start local work | `issue start --file --title` or `--draft`, explicit `--workflow`, optional `--model` | `POST /api/v1/jobs` | Local execution only → review → Create & start locally | Persistent unstarted drafts and typed incident intake remain separate |
14
+ | Browse repository Inbox | `inbox [--page N] [--issue-state open/closed/all]` (also `issue list --source inbox`), `issue preview --url URL` via controller provider | Authenticated `GET /api/v1/issues`, `POST /api/v1/issues/preview` using shared readers | Inbox with provider/state/readiness, loaded-page counts, linked attempts, local/off-page history; explicit Start work for either type | Issue → execution links retained; no implicit polling |
15
+ | Start repository work | `issue start --url URL --workflow software/defence [--brief-file operator.md]` | `POST /api/v1/issues/start` | Issue context → explicit Start work with operator brief | Rechecks current content and active admission |
15
16
  | Create repository issue / recovery | `issue connection`, `create --key`, `submissions`, `recover --key` | Authenticated connection, `POST /issues`, receipts and recovery | Display destination/actor, create without execution, recover uncertain result | GitHub adapter first; assignees/projects and other providers unimplemented |
16
17
  | Repository issue templates | `issue templates`, `issue draft --template --sha --file` | Authenticated template list and draft compilation | Chooser, fields/defaults/validation, review | Supports Markdown and YAML markdown/input/textarea/dropdown/checkboxes; unsupported templates link to GitHub |
17
18
  | Suggest task type | `issue recommend --file` or `--url` | Authenticated `POST /api/v1/intake/recommend`; issue preview includes suggestion | Editable recommendation after source selection | Deterministic label/brief rules; no model judgment or execution authority |
@@ -32,7 +33,7 @@ shell endpoint or a second scheduler.
32
33
  | SSH tunnels | `tunnel` | No tunnel endpoint | None | Client-host ownership; distinguish operator machine from worker |
33
34
  | Method export | `kit --output` | No export endpoint | None | Equivalent download/export preserving staging-only adoption |
34
35
  | Synthetic qualification | `demo`, `qualify` | No qualification endpoint | Synthetic disclosure only | Explicit separate state; never target an application accidentally |
35
- | Immutable source admission | `init --source-ref`, `run --source-ref`, `issue start --source-ref`; status and build evidence carry the resolved SHA | `POST /api/v1/jobs` resolves/retains before acknowledgement; shared source metadata in status | New issue and revision forms accept a ref; task detail shows requested ref, resolved SHA and prior source commits | Build/retry use retained objects; revisions start fresh by default; explicit continuation keeps the reviewed tree and recorded source; a new ref replaces the base; legacy source remains unknown |
36
+ | Immutable source admission | `init --source-ref`, `run --source-ref`, `issue start --source-ref`; status and build evidence carry the resolved SHA | `POST /api/v1/jobs` resolves/retains before acknowledgement; shared source metadata in status | Issue Start work, local request and revision forms accept a ref; task detail shows requested ref, resolved SHA and prior source commits | Build/retry use retained objects; revisions start fresh by default; explicit continuation keeps the reviewed tree and recorded source; a new ref replaces the base; legacy source remains unknown |
36
37
  | Trusted PR handoff | `publish JOB_ID` publishes/reconciles; `abandon-delivery JOB_ID --branch-sha SHA` records a checked local resolution for a pre-write branch collision | Authenticated `POST /api/v1/jobs/:id/publish` and `/abandon-delivery`; shared receipt, conflict identity and removal policy | Publish/reconcile and explicit “Abandon local delivery; keep remote branch” actions share controller state; errors/results and inspected branch identity are visible | New writes require matching protected Codex/Pi build/review provenance, deterministic verify/handoff provenance, non-synthetic bound artifacts and a qualified GitHub Actions tree. Shared delivery status exposes `workflow_qualification` and the same reason blocks CLI/API/dashboard capability and publication/retry. Candidate workflow changes, unsupported triggers/syntax, or active generated-push, selected-ref-dispatch and PR jobs with write/secrets/environment/OIDC/deploy access, self-hosted runners or ambiguous privileged guards refuse trusted writes. Supported ASCII guard comparisons follow GitHub's case-insensitive string semantics; unknown PR refs, non-ASCII mismatches, and glob/escaped branch filters cannot prove a privileged job inactive. The shared summary's `action_mode` distinguishes new/resumable publication from read-only reconciliation and drives idle and pending task button wording. Branch-only collisions and unknown/abandoned states offer neither; known PR receipts and pending PR-creation checkpoints retain read-only reconciliation. Abandonment checks the current run, saved intent, exact branch head and absence of an associated PR; it writes no provider data, preserves the remote branch/evidence, disables republishing and permits local removal. Uncertain effects and incompatible evidence stay blocked. Destination remains private operator config; patch-only remains default |
37
38
  | Optional trusted web verification | `web probe` performs a real local Chromium interaction; `doctor` reports readiness | Verify stores a shared story summary and protected JSON artifact in the run | Task history shows passed/failed/unavailable/inconclusive plus tool, candidate, policy and story hashes | Disabled by default. Required operator stories and Playwright/Chromium image ID are frozen in attempt policy. Linux Chromium proof cannot qualify native/mobile OS behavior; see [the browser contract](web-verification.md) |
38
39
 
@@ -57,3 +58,51 @@ the Skills page reads that same file. Full safe setup controls remain #37.
57
58
  The roadmap is split into Defence #50, quality measurement #51, GitHub intake
58
59
  #52, editable definitions #53 and scoped MCP #54. Existing REST endpoints are
59
60
  local single-operator interfaces, not a public multi-user API.
61
+
62
+
63
+ ## Issue lifecycle API in 0.11.0
64
+
65
+ `GET /api/v1/issues?page=1&state=open` retains repository/issues/next_page and adds
66
+ provider, page, state, loaded_count, total (null when unknown), and history.
67
+ Each issue adds canonical identity, provider state, readiness, executions,
68
+ latest_execution, active_execution(s), and start_block_reason. History groups
69
+ local jobs and canonical sources outside the page; not_loaded does not claim
70
+ that an issue is missing or closed. `status.issue_history` refreshes these local
71
+ associations without polling the provider. No issue content database was added.
72
+
73
+ `POST /api/v1/issues/preview` retains content/labels/recommendation and adds the
74
+ same identity/readiness/history contract. `POST /api/v1/issues/start` accepts
75
+ url, expected_spec (the preview's spec), workflow, optional brief, source_ref
76
+ and model. It re-reads current provider context, rejects changed scope, closed
77
+ sources, blocked/conflicting readiness and active/unresolved work, then uses
78
+ existing source admission. HTTP 409 describes stale or duplicate admission.
79
+ `POST /api/v1/jobs` remains compatible for local/direct callers; its queue-level
80
+ canonical reservation also rejects concurrent duplicate active work and retries.
81
+ Terminal succeeded/failed/cancelled executions release the reservation unless
82
+ provider delivery is unresolved. Other/unknown states retain it conservatively.
83
+
84
+ `inbox` now defaults to the same repository page object as the dashboard (open,
85
+ page 1), an intentional 0.11.0 JSON change from its former jobs array. Use
86
+ `inbox --source factory` for the explicit legacy execution-only array.
87
+ `issue list` still defaults to the original local jobs array (`--source factory`).
88
+ `--source inbox`, `remote` and compatibility `github` return the shared enriched
89
+ page. `issues` now uses this same authenticated controller endpoint and enriched
90
+ JSON, rather than bypassing the controller; scripts need a running controller.
91
+ Use `--issue-state` for provider state; `--state` continues to mean installation
92
+ path. Repository paging/state options are rejected in execution-only mode rather
93
+ than ignored. Unsupported providers return their capability state and local/history
94
+ records; provider/auth failures exit nonzero, never an empty-success backlog.
95
+ `issue start --url URL --brief-file operator.md` reads a UTF-8 operator brief of at
96
+ most 16000 characters (the API's string-length limit), forwarded unchanged to the
97
+ shared preview/start contract. The API appends nonblank, trimmed text under
98
+ `Operator brief:` in the admitted spec, while preserving provider identity and
99
+ rechecking current content. `--brief-file` is optional, only valid with remote
100
+ `issue start --url` (or its `--github` alias); it cannot accompany local `--file`
101
+ or `--draft`, creation, browsing or other commands. Missing/unreadable files and
102
+ oversize text fail without admission. Local file/draft execution is unchanged. `run` retains
103
+ its compatible direct-job path and the controller's duplicate identity guard.
104
+
105
+ Definition exposes `configuration.issueReadinessLabels`. The optional private
106
+ config field has exactly triage/spec/ready/blocked keys with four distinct label
107
+ names; defaults are factory:triage/spec/ready/blocked. Configuration is validated,
108
+ not inferred from issue content. No browsing path changes labels or comments.
package/docs/npm.md CHANGED
@@ -4,24 +4,53 @@ Requires Node 22.13 or later. The method export needs no Docker. Running jobs
4
4
  also requires Git and a running Docker Engine or Docker Desktop on Linux/macOS.
5
5
 
6
6
  ```sh
7
- npm install --global software-defence-factory
8
- software-defence-factory help
7
+ npm install --global software-defence-factory@latest
8
+ factory help
9
9
  ```
10
10
 
11
11
  For a one-off invocation:
12
12
 
13
13
  ```sh
14
- npx software-defence-factory@latest help
14
+ npm exec --package=software-defence-factory@latest -- factory help
15
15
  ```
16
16
 
17
17
  Both commands use the same package. A development checkout is unnecessary.
18
- Use `software-defence-factory kit --output /new/staging/directory` to export the portable
18
+ Use `factory kit --output /new/staging/directory` to export the portable
19
19
  method. It refuses an existing destination and does not modify an app. Use
20
- `software-defence-factory init --repo /path/to/app --harness codex --check "npm ci && npm test"`
20
+ `factory init --repo /path/to/app --harness codex --check "npm ci && npm test"`
21
21
  only when configuring the optional local job runner. `init` does not start jobs,
22
22
  copy skills into the app, or copy account credentials. Runtime jobs receive the
23
23
  bundled policy and skills directly. Model access is configured separately.
24
24
 
25
+ ## Executable and package compatibility
26
+
27
+ Starting with 0.11.1, `factory` and `software-defence-factory` are bin aliases
28
+ for `bin/software-defence-factory.mjs`. They share one runtime, state and updater.
29
+ The npm package is still `software-defence-factory`, published by Arcitai from
30
+ `arcitai/software-and-defence-factory`. Release qualification is tracked in
31
+ [#61](https://github.com/arcitai/software-and-defence-factory/issues/61) and its linked delivery PRs.
32
+
33
+ An older global bootstrap upgraded through the private release cache keeps
34
+ working through `software-defence-factory`, including offline cached dispatch.
35
+ It does **not** gain a global `factory` symlink. To expose both bins with
36
+ 0.11.1 or later, stop and reconcile installations, check `command -v factory`, then run
37
+ `npm install --global software-defence-factory@latest`.
38
+ If that name belongs to another tool, keep the compatibility executable or use
39
+ `npm exec --package=software-defence-factory@latest -- factory ...`. Do not use
40
+ `--force` to replace another program. npm refuses a conflicting unrelated bin.
41
+ Both bin keys point to the same file; tarball tests cover explicit executable
42
+ selection through npm exec and npx. The syntax above avoids relying
43
+ on package-name inference. Never use `npx factory` or `npm install factory` for
44
+ this product.
45
+
46
+ The selected successor package is `factory-sd`, but account/OIDC prerequisites
47
+ and namespace cutover remain pending under [#61](https://github.com/arcitai/software-and-defence-factory/issues/61).
48
+ The issue records `factory` as owned by another project and `factory-sd` as a
49
+ registry 404 on 2026-09-26; availability is not a reservation. Before cutover,
50
+ verify replacement publishing trust, package/updater identity, Actions references,
51
+ redirects and an explicit idle/recoverable upgrade route. Reconcile ambiguous
52
+ external-write receipts without replaying them under a renamed repository.
53
+
25
54
  ## Persistent data
26
55
 
27
56
  The npm CLI stores private runtime data under
@@ -34,7 +63,9 @@ the npx cache, or your application repository.
34
63
  Source checkouts retain their existing `.factory/platform` and
35
64
  `.factory/demo-platform` defaults. Stop the old controller before moving an
36
65
  existing state directory. Update its `factory.json` repository path if necessary;
37
- start a fresh state directory for the native 0.3 runtime. Earlier engine journals are not automatically migrated; keep them separately as evidence.
66
+ retain existing jobs, configuration and evidence. Branding requires no state move
67
+ or migration. State/service/tunnel names, configured image IDs, update keys and
68
+ historical policy/record hashes remain unchanged.
38
69
 
39
70
  ## Automatic updates
40
71
 
@@ -50,10 +81,10 @@ and restores their prior running set without interrupting a job. See
50
81
  [services](services.md) for installation, maintenance recovery and limitations.
51
82
 
52
83
  ```sh
53
- software-defence-factory update --check
54
- software-defence-factory update
55
- software-defence-factory update --auto off
56
- software-defence-factory update --auto on
84
+ factory update --check
85
+ factory update
86
+ factory update --auto off
87
+ factory update --auto on
57
88
  ```
58
89
 
59
90
  Updates use npm with lifecycle scripts disabled and retain immutable releases
@@ -73,8 +104,8 @@ installation or retained attempt needs them.
73
104
 
74
105
  ## Protected evidence compatibility
75
106
 
76
- 0.10.0 recognizes version-1 execution profiles emitted by native **0.8.0,
77
- 0.9.0, 0.9.1 and 0.10.0**. This is an exact allowlist in
107
+ Factory 0.11.1 recognizes version-1 execution profiles emitted by native
108
+ **0.8.0, 0.9.0, 0.9.1, 0.10.0, 0.11.0 and 0.11.1**. This is an exact allowlist in
78
109
  `factory/execution-profile.mjs`, independent of the installed package version;
79
110
  it is not a semver range or an automatic promise for later releases. Unknown
80
111
  runtime strings, unknown profile formats and incomplete legacy acceptance
@@ -101,9 +132,9 @@ neither a reason to discard evidence nor proof of compatibility. Retain
101
132
  unsupported records unchanged and obtain fresh applicable evidence through the
102
133
  normal workflow; never repair them by editing private records or hashes.
103
134
 
104
- The 0.10.0 writer retains the same profile format and original-base, aggregate
105
- single-parent candidate/check/review/approval guarantees. Continuation adds
106
- separate provenance; it is not acceptance evidence. The audited 0.8.0, 0.9.0 and
135
+ Versions 0.11.0 and 0.11.1 use the same protected evidence writer and profile
136
+ format, with original-base, aggregate single-parent candidate/check/review/approval
137
+ guarantees. Continuation adds separate provenance; it is not acceptance evidence. The audited 0.8.0, 0.9.0 and
107
138
  0.9.1 writers remain supported only when their old records meet all current
108
139
  checks. For continuation specifically, the current completed review, successful
109
140
  Build/Verify, protected per-attempt artifacts, current policy and clean candidate
@@ -112,14 +143,10 @@ a checkpoint usable. Browser-disabled 0.8.0 records cannot satisfy a newly
112
143
  enabled browser policy. Missing or unsupported records stay unchanged and
113
144
  unavailable; no schema migration, profile relabeling or policy repair occurs.
114
145
 
115
- #71 shipped 0.9.0 through PR #81 and #84 shipped 0.9.1 through PR #85; both
116
- passed installed qualification, as reported by the lead. For this 0.10.0 slice,
117
- native Verify/Review remain required. The lead owns installed continuation,
118
- disposable protected PR/CI and desktop/narrow light/dark browser qualification
119
- on Z13. Controlled source fixtures do not supply that proof. New publication
120
- still requires the current remote target to equal the original accepted base;
121
- reviewed-candidate continuation preserves that baseline, while target refresh
122
- remains #72.
146
+ New publication still requires the current remote target to equal the original
147
+ accepted base; reviewed-candidate continuation preserves that baseline, while
148
+ target refresh remains #72. See [the verification map](https://github.com/arcitai/software-and-defence-factory/blob/main/docs/proof.md) for delivered
149
+ capabilities and the distinction between source checks and installed proof.
123
150
 
124
151
  ## Release flow
125
152
 
@@ -133,20 +160,27 @@ For a release, update both manifests with `npm version patch --no-git-tag-versio
133
160
  review the change, and push through the project's normal review flow. A code
134
161
  push without a version bump is tested but does not overwrite a published package.
135
162
 
136
- The first release is published by the maintainer. Then configure npm trusted
137
- publishing for GitHub owner `arcitai`, repository `software-and-defence-factory`,
138
- workflow filename `ci.yml`, with direct publishing enabled. Subsequent releases
139
- use short-lived OIDC authentication; no npm write token belongs in the repo or
140
- Z13. The source repository remains private, so npm cannot issue public source
141
- provenance for it. The public npm package contains an explicit runtime/method
163
+ The current trusted-publisher identity is npm package `software-defence-factory`,
164
+ GitHub owner `arcitai`, repository `software-and-defence-factory`,
165
+ workflow filename `ci.yml`. The workflow uses short-lived OIDC authentication.
166
+ The source repository is **public**, but the current workflow explicitly sets
167
+ `NPM_CONFIG_PROVENANCE=false`; OIDC authenticates publication and does not mean
168
+ this release emits npm provenance. No npm write token belongs in the repository
169
+ or agent jobs. The public npm package contains an explicit runtime/method
142
170
  allowlist, excluding operational state, account data and retired research. It includes the explicitly labelled synthetic runtime fixture used by demo and qualification.
143
171
 
144
- Set the GitHub repository variable `NPM_PUBLISH_ENABLED=true` only after that
145
- first publication and trusted-publisher binding are complete. Until then CI
146
- still builds and tests every change, while publishing is deliberately skipped.
172
+ Publication requires repository variable `NPM_PUBLISH_ENABLED=true` and the
173
+ matching npm account binding. Preserve the working identity until replacement
174
+ trust is verified. Changes must pass the normal protected PR/CI flow; do not
175
+ weaken protection or bypass merge checks.
147
176
  After a CLI update, restart a stopped dashboard with `up --state PATH` and refresh
148
177
  the browser to load the new bundled interface. Updates do not replace the code
149
178
  of a controller that is still running.
150
179
 
180
+ The installed native publisher refuses `.github/workflows` changes. Keep that
181
+ guard. Automated GitHub Releases, immutable tags, registry readback and recovery
182
+ after npm succeeds but Release creation fails remain a separate maintainer
183
+ delivery under [#61](https://github.com/arcitai/software-and-defence-factory/issues/61).
184
+
151
185
  References: [npm/npx](https://docs.npmjs.com/cli/v11/commands/npx/),
152
186
  [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/).
package/docs/ownership.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Ownership and provenance
2
2
 
3
- Software & Defence Factory is developed by Arcitai. Original CLI, native Node/SQLite runtime, container boundary, incident intake, updater, method and six skills are maintained in this repository under MIT.
3
+ Factory is developed by Arcitai. Original CLI, native Node/SQLite runtime, container boundary, incident intake, updater, method and six skills are maintained in this repository under MIT.
4
4
 
5
5
  The dashboard retains the selected third-party interface and interaction model, with modified branding and a factory-owned API integration. Its original copyright, source revision and permission notice are retained in [THIRD_PARTY_NOTICES.md](../THIRD_PARTY_NOTICES.md), together with notices for bundled UI components and fonts. Those notices are required source attribution, not runtime dependencies or product branding.
6
6
 
7
- The installed package includes no personal AIOS home, private owner memory or external agent plugin. A skill is an instruction, not a bundled browser, model subscription, provider account or security scanner. Codex/Pi are separately licensed tools included by the pinned Docker build; the operator supplies authorized inference access.
7
+ A skill is an instruction, not a bundled browser, model subscription, provider account or security scanner. Codex/Pi are separately licensed tools included by the pinned Docker build; the operator supplies authorized inference access.
8
8
 
9
- Earlier research and prototype implementations remain in Git history. Their historical evaluation claims do not establish qualification of the current runtime. Current evidence is recorded in [proof](proof.md).
9
+ Current verification boundaries are recorded in [proof](https://github.com/arcitai/software-and-defence-factory/blob/main/docs/proof.md).
@@ -2,18 +2,18 @@
2
2
 
3
3
  For a new execution host or remote operator, start with the [setup plan](setup.md).
4
4
 
5
- Install Node 22.13+, Git and Docker Engine/Desktop. Use an unprivileged account with Docker access. Install `software-defence-factory` through npm, or invoke the same package with npx. No factory source checkout is required.
5
+ Install Node 22.13+, Git and Docker Engine/Desktop. Use an unprivileged account with Docker access. Install `software-defence-factory` through npm, or use `npm exec --package=software-defence-factory@latest -- factory help`. No factory source checkout is required.
6
6
 
7
7
  ## Qualify a synthetic installation
8
8
 
9
9
  ```sh
10
- software-defence-factory demo
10
+ factory demo
11
11
  ```
12
12
 
13
13
  Open the printed localhost URL, inspect the sample task and its files, then approve the handoff. This changes only an isolated synthetic repository and makes no inference calls. Once the sample finishes:
14
14
 
15
15
  ```sh
16
- software-defence-factory qualify --state /absolute/path/printed/by/demo
16
+ factory qualify --state /absolute/path/printed/by/demo
17
17
  ```
18
18
 
19
19
  The qualification intentionally creates failed, cancelled and interrupted tasks. They are expected evidence of failure handling. Never point qualification at an application installation.
@@ -23,9 +23,9 @@ The qualification intentionally creates failed, cancelled and interrupted tasks.
23
23
  Commit an intentional, reviewed starting point in the application first. Jobs clone committed code only; uncommitted work stays in the source checkout.
24
24
 
25
25
  ```sh
26
- software-defence-factory init --repo /absolute/path/to/app --harness codex --check "npm ci && npm test" --source-ref main --state /private/state/my-app --port 7331
27
- software-defence-factory install --state /private/state/my-app
28
- software-defence-factory doctor --state /private/state/my-app
26
+ factory init --repo /absolute/path/to/app --harness codex --check "npm ci && npm test" --source-ref main --state /private/state/my-app --port 7331
27
+ factory install --state /private/state/my-app
28
+ factory doctor --state /private/state/my-app
29
29
  ```
30
30
 
31
31
  `init --source-ref` selects the configured default ref (`HEAD` when omitted). Each job resolves that ref, or an explicit `--source-ref` on `run`/`issue start`, in the configured repository and durably retains its commit before acknowledging admission. It records the canonical GitHub origin identity when available; the CLI and dashboard show the requested ref and resolved SHA. Task text and reference links do not select a repository, source ref or PR target.
@@ -71,8 +71,8 @@ container. Host loopback addresses do not automatically refer to the host from
71
71
  Docker. The package does not automatically expose Ollama or import models.
72
72
 
73
73
  ```sh
74
- software-defence-factory up --state /private/state/my-app
75
- software-defence-factory run --file task.md --source-ref main --state /private/state/my-app
74
+ factory up --state /private/state/my-app
75
+ factory run --file task.md --source-ref main --state /private/state/my-app
76
76
  ```
77
77
 
78
78
  A task should describe the accepted outcome, allowed scope and observable checks. The CLI also accepts `--issue https://github.com/owner/repo/issues/123` for an issue belonging to the configured origin; it uses the operator's existing gh access outside the job. The dashboard supports the same task workflow. Source text and links do not grant additional authority.
@@ -90,7 +90,7 @@ canonical GitHub origin and an explicit target while initializing the private
90
90
  installation:
91
91
 
92
92
  ```sh
93
- software-defence-factory init --repo /absolute/path/to/app --harness codex \
93
+ factory init --repo /absolute/path/to/app --harness codex \
94
94
  --check "npm ci && npm test" --source-ref main \
95
95
  --delivery-provider github \
96
96
  --delivery-repository https://github.com/OWNER/REPO \
@@ -109,7 +109,7 @@ After the ordinary check, independent review and operator approval complete,
109
109
  use **Publish accepted candidate as draft PR** in task details or run:
110
110
 
111
111
  ```sh
112
- software-defence-factory publish JOB_ID --state /private/state/my-app
112
+ factory publish JOB_ID --state /private/state/my-app
113
113
  ```
114
114
 
115
115
  Trusted publication requires protected per-run execution records for native
@@ -149,7 +149,7 @@ create a second PR or overwrite a changed branch. The CLI gives this bounded
149
149
  multi-request action ten minutes; branch resolution uses the same bound and
150
150
  other API calls keep their five-second deadline. If a client deadline expires,
151
151
  inspect status and repeat `publish` to reconcile or recheck the reported branch
152
- identity before `abandon-delivery`. Delete issue stays disabled while delivery
152
+ identity before `abandon-delivery`. Remove local execution history stays disabled while delivery
153
153
  is unresolved, and the controller enforces the same guard on its API.
154
154
  Publication does not merge, integrate, release or deploy. See [delivery
155
155
  recovery](recovery.md#trusted-pr-delivery).
@@ -179,8 +179,8 @@ Build a compatible application image on the execution host, then select its exis
179
179
  local tag through the CLI:
180
180
 
181
181
  ```sh
182
- software-defence-factory install --image LOCAL_IMAGE_REF --state /private/state/my-app
183
- software-defence-factory doctor --state /private/state/my-app
182
+ factory install --image LOCAL_IMAGE_REF --state /private/state/my-app
183
+ factory doctor --state /private/state/my-app
184
184
  ```
185
185
 
186
186
  Selection resolves and retains the immutable image ID. It does not pull or build
@@ -211,8 +211,7 @@ use the [Defence integration](defence-integration.md) recipe; the generic
211
211
  Defence form is not that typed intake path.
212
212
 
213
213
  The header names the configured project. View repo opens a validated GitHub
214
- origin. New issue opens Factory’s local chooser: repository templates, a blank
215
- form or existing GitHub issues. Create issue saves to the supported repository provider without execution. Start work queues local work. See [intake and CLI examples](workflows.md). The task detail provides previous/next within the filtered list, copy
214
+ origin. Inbox lists repository issues directly with open/closed/all filters and paging. New issue opens repository templates or a blank creation form. Create issue saves to the supported repository provider without execution. Open an issue from Inbox and choose Start work to admit execution explicitly. The controller rejects duplicate active work; linked attempts remain accessible. See [intake and CLI examples](workflows.md). The task detail provides previous/next within the filtered list, copy
216
215
  link and close (Escape). Closing preserves the list's filters and position.
217
216
 
218
217
  If the interface looks unexpectedly small, check the browser zoom. The design
@@ -229,5 +228,5 @@ is unnecessary for this CLI. Optional
229
228
  process settings are `SDF_AUTO_UPDATE=0` (skip automatic CLI update checks),
230
229
  `XDG_STATE_HOME`, `XDG_DATA_HOME` and `XDG_CONFIG_HOME` (user-owned state, release
231
230
  and service locations). They must be exported in the process environment.
232
- Legacy prototype names such as `FACTORY_WORKER_CONFIG`, `FACTORY_MODEL`, `PORT`
231
+ Unsupported environment variables such as `FACTORY_WORKER_CONFIG`, `FACTORY_MODEL`, `PORT`
233
232
  and `FACTORY_DEMO` are not supported. See [concepts](concepts.md).