@awebai/oats 0.24.1 → 0.24.3
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/bin/oats.mjs +227 -19
- package/capabilities/oats-aweb/bin/oats-aweb-binding.mjs +11 -0
- package/capabilities/oats-aweb/bin/oats-aweb.mjs +26 -0
- package/capabilities/oats-aweb/lib/binding-wire.mjs +214 -0
- package/capabilities/oats-aweb/lib/captured-execution.mjs +91 -0
- package/capabilities/oats-aweb/lib/captured-native.mjs +91 -0
- package/capabilities/oats-aweb/lib/invocation-shape.mjs +135 -0
- package/capabilities/oats-aweb/lib/portable-binding.mjs +146 -0
- package/capabilities/oats-aweb/lib/session-readiness.mjs +56 -0
- package/capabilities/oats-aweb/oats.json +12 -3
- package/docs/design/2026-09-20-redesign-program-board.md +28 -15
- package/docs/design/2026-09-20-workspace-onboarding-public.md +73 -7
- package/docs/first-team.md +42 -0
- package/docs/layers.md +1 -1
- package/docs/official-marketplace.md +14 -9
- package/docs/packages.md +11 -7
- package/docs/release-notes/v0.24.2.md +21 -0
- package/docs/release-notes/v0.24.3.md +13 -0
- package/docs/souls-and-instances.md +25 -0
- package/docs/workspace-adoption.md +94 -65
- package/injects/oats-portable.md +4 -0
- package/lib/core.mjs +65 -19
- package/lib/portable-onboarding.mjs +3 -3
- package/lib/prepared-bindings.mjs +21 -8
- package/lib/provider-binding-broker.mjs +6 -1
- package/lib/setup-expert-source.mjs +76 -0
- package/package-catalog.json +7 -4
- package/package.json +3 -1
- package/souls/oats-setup-expert/AGENTS.md +60 -0
- package/souls/oats-setup-expert/soul.yaml +14 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { validateInvocationShape, sameInvocationJson } from './invocation-shape.mjs';
|
|
2
|
+
export const MESSAGING_CONTRACT='oats.aweb.messaging';
|
|
3
|
+
export const MESSAGING_CONTRACT_VERSION=1;
|
|
4
|
+
export const RESPONSIBLE_HUMAN_KEY='/bindings/messaging/responsibleHuman';
|
|
5
|
+
export const PRIVATE_TEAM_KEY='/bindings/messaging/privateTeam';
|
|
6
|
+
export const WIDER_KEY='/bindings/messaging/wider';
|
|
7
|
+
const CAPABILITY='oats.aweb';
|
|
8
|
+
const identifierPattern=/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,95}$/;
|
|
9
|
+
const obj=value=>value!==null && typeof value==='object' && !Array.isArray(value);
|
|
10
|
+
const clone=value=>JSON.parse(JSON.stringify(value));
|
|
11
|
+
const canonical=value=>value===null || typeof value!=='object'?JSON.stringify(value):Array.isArray(value)?`[${value.map(canonical).join(',')}]`:`{${Object.keys(value).sort().map(key=>`${JSON.stringify(key)}:${canonical(value[key])}`).join(',')}}`;
|
|
12
|
+
const same=(a,b)=>canonical(a)===canonical(b);
|
|
13
|
+
const fail=(code,message)=>{throw Object.assign(new Error(message),{code});};
|
|
14
|
+
function keys(value,allowed,required,label) {
|
|
15
|
+
if(!obj(value)) fail('invalid-binding',`${label} must be an object`);
|
|
16
|
+
for(const key of Object.keys(value)) if(!allowed.includes(key)) fail('invalid-binding',`unknown ${label} property: ${key}`);
|
|
17
|
+
for(const key of required) if(!Object.hasOwn(value,key)) fail('invalid-binding',`${label} requires ${key}`);
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
function identifier(value,label='identity') {if(typeof value!=='string' || !identifierPattern.test(value) || ['constructor','__proto__','prototype','toString','valueOf'].includes(value)) fail('invalid-binding',`invalid ${label}`);return value;}
|
|
21
|
+
const pointerKey=value=>String(value).replace(/~/g,'~0').replace(/\//g,'~1');
|
|
22
|
+
export const teamChoiceKey=alias=>`/bindings/messaging/teams/${pointerKey(identifier(alias,'team alias'))}`;
|
|
23
|
+
function originAt(declaration,pointer,kind) {
|
|
24
|
+
const found=declaration.origins[pointer] ?? declaration.origin;
|
|
25
|
+
if(!obj(found)) fail('invalid-binding',`missing origin for ${pointer}`);
|
|
26
|
+
return clone({...found,kind});
|
|
27
|
+
}
|
|
28
|
+
function teamRef(value) {
|
|
29
|
+
keys(value,['provider','id'],['provider','id'],'aweb team reference');
|
|
30
|
+
if(value.provider!==CAPABILITY || typeof value.id!=='string' || !/^[^\s:]+:[^\s:]+$/.test(value.id)) fail('invalid-binding','aweb team reference requires provider oats.aweb and canonical team id');
|
|
31
|
+
return {provider:CAPABILITY,id:value.id};
|
|
32
|
+
}
|
|
33
|
+
function humanRef(value) {
|
|
34
|
+
keys(value,['provider','id'],['provider','id'],'responsible human');
|
|
35
|
+
if(value.provider!==CAPABILITY || typeof value.id!=='string' || !value.id.trim()) fail('invalid-binding','responsible human needs a provider-resolvable oats.aweb id');
|
|
36
|
+
return {provider:CAPABILITY,id:value.id.trim()};
|
|
37
|
+
}
|
|
38
|
+
function exactContext(value) {
|
|
39
|
+
if(value?.kind==='workspace') {keys(value,['kind','identity','observation'],['kind','identity','observation'],'workspace context');if(!obj(value.identity) || !obj(value.observation)) fail('invalid-binding','workspace context needs qualified identity and observation');return {kind:'workspace',identity:clone(value.identity)};}
|
|
40
|
+
if(value?.kind==='standalone') {keys(value,['kind','key'],['kind','key'],'standalone context');if(typeof value.key!=='string' || !value.key.trim()) fail('needs-configuration','messaging-enabled standalone preparation needs an explicit context key');return {kind:'standalone',key:value.key.trim()};}
|
|
41
|
+
fail('invalid-binding','unsupported messaging context');
|
|
42
|
+
}
|
|
43
|
+
function boundContext(value) {
|
|
44
|
+
if(value?.kind==='workspace') {keys(value,['kind','identity'],['kind','identity'],'bound workspace context');if(!obj(value.identity)) fail('invalid-binding','bound workspace context needs qualified identity');return clone(value);}
|
|
45
|
+
if(value?.kind==='standalone') {keys(value,['kind','key'],['kind','key'],'bound standalone context');if(typeof value.key!=='string' || !value.key.trim()) fail('invalid-binding','bound standalone context needs an explicit key');return {kind:'standalone',key:value.key.trim()};}
|
|
46
|
+
fail('invalid-binding','unsupported bound messaging context');
|
|
47
|
+
}
|
|
48
|
+
function declaration(value) {
|
|
49
|
+
keys(value,['kind','value','origin','origins'],['kind','value','origin','origins'],'messaging declaration');
|
|
50
|
+
if(!['soul','workspace','adoption','operator'].includes(value.kind) || !obj(value.value) || !obj(value.origin) || !obj(value.origins)) fail('invalid-binding','invalid messaging declaration');
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Emit messaging provider fields for the kernel's single resolver. Team aliases
|
|
55
|
+
* are availability data; only the explicit operator wider list is consent. */
|
|
56
|
+
export function normalizeMessagingDeclarations({declarations,context}={}) {
|
|
57
|
+
if(!Array.isArray(declarations)) fail('invalid-binding','messaging declarations must be an array');
|
|
58
|
+
const exact=exactContext(context),contextOrigin=context?.kind==='workspace'?clone(context.observation):null,requirements=[],candidates=[],teams={},requested=[],requestedOrigins={},aliases={},aliasOrigins={};let soul=null,privatePolicy=false,privatePolicyOrigin=null;
|
|
59
|
+
for(const raw of declarations) {
|
|
60
|
+
const item=declaration(raw);
|
|
61
|
+
// The kernel supplies complete validated source/workspace/operator
|
|
62
|
+
// declarations, including other providers' fields. Consume only messaging
|
|
63
|
+
// fields here; do not impose a second closed schema on the whole document.
|
|
64
|
+
if(item.kind==='soul') {
|
|
65
|
+
if(soul) fail('requirement-conflict','multiple soul messaging declarations');soul=item;
|
|
66
|
+
const list=item.value.teams ?? [];
|
|
67
|
+
if(!Array.isArray(list) || new Set(list).size!==list.length) fail('invalid-binding','soul teams must be a unique array');
|
|
68
|
+
for(let index=0;index<list.length;index++) {const alias=identifier(list[index],'soul team alias');requested.push(alias);requestedOrigins[alias]=originAt(item,`/teams/${index}`,'soul-requirement');}
|
|
69
|
+
} else if(item.kind==='workspace') {
|
|
70
|
+
const value=item.value.teams;if(value===undefined) continue;if(!obj(value)) fail('invalid-binding','workspace teams must be an object');
|
|
71
|
+
for(const [alias,ref] of Object.entries(value)) {
|
|
72
|
+
if(alias==='private') {if(ref!=='per-human') fail('invalid-binding','workspace private team policy must be per-human');privatePolicy=true;privatePolicyOrigin=originAt(item,'/teams/private','workspace-default');continue;}
|
|
73
|
+
const key=teamChoiceKey(alias),origin=originAt(item,`/teams/${pointerKey(alias)}`,'workspace-default');
|
|
74
|
+
teams[alias]=key;candidates.push({key,kind:'workspace-default',value:teamRef(ref),origin});
|
|
75
|
+
}
|
|
76
|
+
} else if(item.kind==='adoption') {
|
|
77
|
+
const value=item.value.teamAliases;if(value===undefined) continue;if(!obj(value)) fail('invalid-binding','adoption teamAliases must be an object');
|
|
78
|
+
for(const [source,target] of Object.entries(value)) {
|
|
79
|
+
identifier(source,'source team alias');identifier(target,'workspace team alias');
|
|
80
|
+
if(Object.hasOwn(aliases,source) && aliases[source]!==target) fail('requirement-conflict','adoption team aliases have conflicting mappings');
|
|
81
|
+
aliases[source]=target;aliasOrigins[source]=originAt(item,`/teamAliases/${pointerKey(source)}`,'import-adoption');
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
const bindings=item.value.bindings;if(bindings===undefined) continue;
|
|
85
|
+
if(!obj(bindings)) fail('invalid-binding','operator bindings must be an object');
|
|
86
|
+
if(Object.hasOwn(bindings,'responsibleHuman')) candidates.push({key:RESPONSIBLE_HUMAN_KEY,kind:'operator',value:humanRef(bindings.responsibleHuman),origin:originAt(item,'/bindings/responsibleHuman','operator')});
|
|
87
|
+
if(Object.hasOwn(bindings,'privateTeam')) candidates.push({key:PRIVATE_TEAM_KEY,kind:'operator',value:teamRef(bindings.privateTeam),origin:originAt(item,'/bindings/privateTeam','operator')});
|
|
88
|
+
if(Object.hasOwn(bindings,'wider')) {
|
|
89
|
+
if(!Array.isArray(bindings.wider) || new Set(bindings.wider).size!==bindings.wider.length) fail('invalid-binding','operator wider consent must be a unique array');
|
|
90
|
+
candidates.push({key:WIDER_KEY,kind:'operator',value:bindings.wider.map(alias=>identifier(alias,'wider team alias')),origin:originAt(item,'/bindings/wider','operator')});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if(!soul) fail('needs-configuration','messaging binding needs one soul declaration');
|
|
95
|
+
if(exact.kind==='workspace' && !privatePolicy) fail('needs-configuration','messaging workspace must declare private: per-human');
|
|
96
|
+
const rootOrigin=originAt(soul,'','soul-requirement');
|
|
97
|
+
requirements.push({key:RESPONSIBLE_HUMAN_KEY,kind:'required',origin:rootOrigin},{key:WIDER_KEY,kind:'required',origin:rootOrigin});
|
|
98
|
+
return {requirements,candidates,model:{contract:MESSAGING_CONTRACT,version:MESSAGING_CONTRACT_VERSION,context:exact,contextOrigin,requested,requestedOrigins,aliases,aliasOrigins,teams,privatePolicy,privatePolicyOrigin}};
|
|
99
|
+
}
|
|
100
|
+
function selected(choices,key,{optional=false}={}) {
|
|
101
|
+
const choice=choices?.[key];if(!obj(choice) || !Object.hasOwn(choice,'value') || choice.value===null) {if(optional)return null;fail('needs-configuration',key===RESPONSIBLE_HUMAN_KEY?'an explicit responsible-human binding is required':key===WIDER_KEY?'an explicit wider-membership consent list is required':'a selected wider-team binding is required');}return choice;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function bindMessagingDomain({model,choices}={}) {
|
|
105
|
+
if(!obj(model) || model.contract!==MESSAGING_CONTRACT || model.version!==MESSAGING_CONTRACT_VERSION) fail('invalid-binding','invalid normalized messaging model');
|
|
106
|
+
const humanChoice=selected(choices,RESPONSIBLE_HUMAN_KEY),widerChoice=selected(choices,WIDER_KEY),human=humanRef(humanChoice.value);
|
|
107
|
+
if(!Array.isArray(widerChoice.value) || new Set(widerChoice.value).size!==widerChoice.value.length) fail('invalid-binding','resolved wider consent must be a unique array');
|
|
108
|
+
const wider=[],provenance=[humanChoice.selectedBy,widerChoice.selectedBy,model.contextOrigin,model.privatePolicyOrigin].filter(obj).map(clone);
|
|
109
|
+
for(const sourceAlias of widerChoice.value) {
|
|
110
|
+
identifier(sourceAlias,'wider team alias');if(!model.requested.includes(sourceAlias)) fail('invalid-binding',`wider consent names undeclared soul alias: ${sourceAlias}`);
|
|
111
|
+
const workspaceAlias=model.aliases[sourceAlias] ?? sourceAlias,key=model.teams[workspaceAlias];if(!key) fail('needs-configuration','a selected wider alias needs an explicit workspace team mapping');
|
|
112
|
+
const choice=selected(choices,key),ref=teamRef(choice.value);wider.push(ref);if(obj(choice.selectedBy)) provenance.push(clone(choice.selectedBy));
|
|
113
|
+
if(obj(model.requestedOrigins[sourceAlias])) provenance.push(clone(model.requestedOrigins[sourceAlias]));
|
|
114
|
+
if(obj(model.aliasOrigins[sourceAlias])) provenance.push(clone(model.aliasOrigins[sourceAlias]));
|
|
115
|
+
}
|
|
116
|
+
wider.sort((a,b)=>Buffer.compare(Buffer.from(canonical(a)),Buffer.from(canonical(b))));
|
|
117
|
+
for(let index=1;index<wider.length;index++) if(same(wider[index-1],wider[index])) fail('invalid-binding','duplicate resolved wider team');
|
|
118
|
+
const privateChoice=selected(choices,PRIVATE_TEAM_KEY,{optional:true}),privateTeam=privateChoice?teamRef(privateChoice.value):null;if(privateTeam && wider.some(item=>same(item,privateTeam))) fail('invalid-binding','private team cannot also be a wider team');if(obj(privateChoice?.selectedBy)) provenance.push(clone(privateChoice.selectedBy));
|
|
119
|
+
const unique=[];for(const item of provenance) if(!unique.some(prior=>same(prior,item))) unique.push(item);
|
|
120
|
+
const privateKey={provider:CAPABILITY,human,context:clone(model.context)};
|
|
121
|
+
return {payloadContract:MESSAGING_CONTRACT,payloadVersion:MESSAGING_CONTRACT_VERSION,payload:{responsibleHuman:human,context:clone(model.context),privateTeam,wider},credentialRefs:{},provenance:unique,
|
|
122
|
+
messagingChoice:{schemaVersion:1,enabled:true,privateKey,wider:clone(wider),provenance:clone(unique)}};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function validateAwebBinding(binding) {
|
|
126
|
+
keys(binding,['schemaVersion','capability','payloadContract','payloadVersion','payload','credentialRefs','provenance'],['schemaVersion','capability','payloadContract','payloadVersion','payload','credentialRefs','provenance'],'aweb provider binding');
|
|
127
|
+
if(binding.schemaVersion!==1 || binding.capability!==CAPABILITY || binding.payloadContract!==MESSAGING_CONTRACT || binding.payloadVersion!==MESSAGING_CONTRACT_VERSION || !obj(binding.payload) || !obj(binding.credentialRefs) || !Array.isArray(binding.provenance)) fail('invalid-binding','invalid aweb provider binding');
|
|
128
|
+
keys(binding.payload,['responsibleHuman','context','privateTeam','wider'],['responsibleHuman','context','privateTeam','wider'],'aweb binding payload');
|
|
129
|
+
humanRef(binding.payload.responsibleHuman);boundContext(binding.payload.context);if(!Array.isArray(binding.payload.wider)) fail('invalid-binding','aweb wider teams must be an array');
|
|
130
|
+
const wider=binding.payload.wider.map(teamRef);for(let index=1;index<wider.length;index++) {if(same(wider[index-1],wider[index])) fail('invalid-binding','duplicate aweb wider team');if(Buffer.compare(Buffer.from(canonical(wider[index-1])),Buffer.from(canonical(wider[index])))>0) fail('invalid-binding','aweb wider teams are not canonical');}
|
|
131
|
+
if(binding.payload.privateTeam!==null) {
|
|
132
|
+
const privateTeam=teamRef(binding.payload.privateTeam);
|
|
133
|
+
if(wider.some(team=>same(team,privateTeam))) fail('invalid-binding','private team cannot also be a wider team');
|
|
134
|
+
}
|
|
135
|
+
if(Object.keys(binding.credentialRefs).length) fail('invalid-binding','no credential reference shape is supported by this binding version');
|
|
136
|
+
return binding;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function validateAwebInvocationContext(value,binding,expected={}) {
|
|
140
|
+
validateAwebBinding(binding);
|
|
141
|
+
validateInvocationShape(value,{...expected,capability:CAPABILITY});
|
|
142
|
+
const selected=value.context.kind==='workspace'?{kind:'workspace',identity:value.context.identity}:value.context;
|
|
143
|
+
if(value.messagingChoice.enabled!==true || value.messagingChoice.privateKey.provider!==CAPABILITY || !sameInvocationJson(selected,binding.payload.context)
|
|
144
|
+
|| !sameInvocationJson(value.responsibleHuman,binding.payload.responsibleHuman) || !sameInvocationJson(value.messagingChoice.wider,binding.payload.wider)) fail('invalid-binding','invocation contradicts messaging binding');
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Capability-owned operational readiness for the existing HOME delivery route.
|
|
2
|
+
// This is not human-account delegation, private-grant proof or model completion.
|
|
3
|
+
import {execFileSync} from 'node:child_process';
|
|
4
|
+
import {isAbsolute,resolve} from 'node:path';
|
|
5
|
+
import {BINDING_WIRE_LIMITS,parseBindingJson} from './binding-wire.mjs';
|
|
6
|
+
import {sameInvocationJson as same} from './invocation-shape.mjs';
|
|
7
|
+
import {validateAwebBinding,validateAwebInvocationContext} from './portable-binding.mjs';
|
|
8
|
+
// 0.24.1 supplies HOME custody; 0.24.2 also ships the required public projection
|
|
9
|
+
// and same-kernel codec CLI locator. Source presence is not a released version.
|
|
10
|
+
export const HOME_ROUTE_KERNEL_FLOOR='0.24.2';
|
|
11
|
+
const obj=v=>v!==null&&typeof v==='object'&&!Array.isArray(v);
|
|
12
|
+
const missing=message=>({status:'needs-configuration',problems:[{code:'needs-configuration',message}]});
|
|
13
|
+
const error=()=>{throw Object.assign(new Error('selected kernel observation unavailable'),{code:'provider-unavailable'});};
|
|
14
|
+
/** Preserve native HOME/profile/auth/Git; remove only the invoking instance's
|
|
15
|
+
* OATS selectors so a read-only query cannot accidentally target its parent. */
|
|
16
|
+
export function kernelQueryEnvironment(inherited){
|
|
17
|
+
const env={...inherited};
|
|
18
|
+
for(const key of Object.keys(env))if(/^(OATS_(?!HOME_DIR$)|OAS_|PI_AGENT_)/.test(key)||key==='PI_AGENTS_ROOT')delete env[key];
|
|
19
|
+
return env;
|
|
20
|
+
}
|
|
21
|
+
export function kernelMeetsHomeRouteFloor(version){
|
|
22
|
+
if(typeof version!=='string'||!/^\d+\.\d+\.\d+$/.test(version))return false;
|
|
23
|
+
const parts=version.split('.').map(Number),floor=HOME_ROUTE_KERNEL_FLOOR.split('.').map(Number);if(!parts.every(Number.isSafeInteger))return false;
|
|
24
|
+
for(let i=0;i<3;i++)if(parts[i]!==floor[i])return parts[i]>floor[i];
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
/** Use the caller-owned CLI location, never search PATH or import private kernel
|
|
28
|
+
* indexes. Binding execution must receive the same OATS_CLI_BIN as hooks. */
|
|
29
|
+
export function querySelectedKernel(args,{env=process.env}={}){
|
|
30
|
+
const cli=env.OATS_CLI_BIN;
|
|
31
|
+
if(typeof cli!=='string'||!isAbsolute(cli)||resolve(cli)!==cli||cli.includes('\0'))error();
|
|
32
|
+
let bytes;
|
|
33
|
+
try{bytes=execFileSync(process.execPath,[cli,...args],{env:kernelQueryEnvironment(env),timeout:10000,maxBuffer:BINDING_WIRE_LIMITS.bytes,stdio:['ignore','pipe','pipe']});}catch{error();}
|
|
34
|
+
try{return parseBindingJson(bytes,BINDING_WIRE_LIMITS);}catch{error();}
|
|
35
|
+
}
|
|
36
|
+
/** Reads only public version/retained selection. A missing profile projection
|
|
37
|
+
* stays explicit; no source default, mutable home label or runtime guess. */
|
|
38
|
+
export function assessCapturedSessionReadiness({binding,invocation,settings},{query=querySelectedKernel,env=process.env}={}){
|
|
39
|
+
if(!binding||!invocation)return missing('selected binding and inline captured invocation are required');
|
|
40
|
+
validateAwebBinding(binding);validateAwebInvocationContext(invocation,binding);
|
|
41
|
+
if(!invocation.instance)return missing('an explicit captured instance home is required');
|
|
42
|
+
if(binding.payload.privateTeam===null)return missing('an explicit private-team binding is required');
|
|
43
|
+
if(settings.delivery!=='session')return missing('captured messaging requires explicit delivery: session');
|
|
44
|
+
if(binding.payload.wider.length)return missing('selected wider memberships need their explicitly qualified native setup; they were not omitted');
|
|
45
|
+
let version,observed;
|
|
46
|
+
try{version=query(['--version','--json'],{env});}catch{return missing('caller-owned OATS_CLI_BIN and readable kernel version are required');}
|
|
47
|
+
if(version?.schemaVersion!==1||version?.name!=='@awebai/oats'||!kernelMeetsHomeRouteFloor(version.version))return missing('oats >=0.24.2 is required for captured HOME custody and retained runtime inspection');
|
|
48
|
+
const b=invocation.executionBinding;
|
|
49
|
+
try{observed=query(['inspect','--deployment',b.deployment,'--resolution',b.resolution.id,'--json'],{env});}catch{return missing('the exact retained runtime profile must be readable');}
|
|
50
|
+
if(observed?.schemaVersion!==1||observed?.ok!==true||!same(observed.result?.resolution,b.resolution))return missing('the kernel must report the exact retained resolution');
|
|
51
|
+
const launch=observed.result.launchSelection;
|
|
52
|
+
if(!obj(launch)||Object.keys(launch).some(k=>!['runtime','model'].includes(k))||!Object.hasOwn(launch,'model')||(launch.model!==null&&(typeof launch.model!=='string'||!launch.model.trim())))return missing('a retained launchSelection runtime/model observation is required');
|
|
53
|
+
if(launch.runtime==='pi')return missing('Pi strict print does not support session input; retain messaging and configure an input-capable profile');
|
|
54
|
+
if(!['claude','codex'].includes(launch.runtime))return missing('a supported input-capable ordinary Claude/Codex profile is required');
|
|
55
|
+
return {status:'ready',problems:[]};
|
|
56
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"capability": "oats.aweb",
|
|
3
3
|
"command": "aweb",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.11.0",
|
|
5
5
|
"compatibility": {
|
|
6
|
-
"oats": ">=0.
|
|
6
|
+
"oats": ">=0.24.2"
|
|
7
7
|
},
|
|
8
8
|
"layer": "messaging",
|
|
9
9
|
"description": "Messaging layer via aweb: per-instance team identities + native aw mail/chat skills + cross-machine team roster.",
|
|
@@ -64,7 +64,16 @@
|
|
|
64
64
|
"inject": "injects/aweb.md",
|
|
65
65
|
"commands": {
|
|
66
66
|
"roster": "bin/oats-aweb.mjs roster",
|
|
67
|
-
"setup": "bin/oats-aweb.mjs setup"
|
|
67
|
+
"setup": "bin/oats-aweb.mjs setup",
|
|
68
|
+
"binding-normalize": "bin/oats-aweb-binding.mjs normalize",
|
|
69
|
+
"binding-bind": "bin/oats-aweb-binding.mjs bind",
|
|
70
|
+
"binding-check": "bin/oats-aweb-binding.mjs check"
|
|
71
|
+
},
|
|
72
|
+
"binding": {
|
|
73
|
+
"version": 1,
|
|
74
|
+
"normalize": "binding-normalize",
|
|
75
|
+
"bind": "binding-bind",
|
|
76
|
+
"check": "binding-check"
|
|
68
77
|
},
|
|
69
78
|
"hooks": {
|
|
70
79
|
"spawn": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Purpose:** the one accurate view of every work stream in the redesign, what is on main, what is in flight, who owns it, and what blocks it. Lead: `oats-expert` (redesign lead). Updated whenever anything merges, is returned, or reality changes. Older per-lane boards are superseded by this file.
|
|
4
4
|
|
|
5
|
-
**Last update:** 2026-09-
|
|
5
|
+
**Last update:** 2026-09-21 05:00Z · main `04e930e7` · **OATS v0.24.2 published** · OKF v2.1.1 · oats-framework/v1.1.1 · aweb v1.11.0 · oats-knowledge 8d67eab4
|
|
6
6
|
|
|
7
7
|
Legend: ✅ on main/published · 🔄 in flight (PR/branch) · 🟡 preserved, not adopted · ⬜ not started · ⛔ blocked
|
|
8
8
|
|
|
@@ -10,14 +10,14 @@ Legend: ✅ on main/published · 🔄 in flight (PR/branch) · 🟡 preserved, n
|
|
|
10
10
|
|
|
11
11
|
| # | Stream | State | Owner | Next action |
|
|
12
12
|
|---|---|---|---|---|
|
|
13
|
-
| S1 | Knowledge capability contract rework (kernel↔provider boundary, OKF 2.x) | ✅
|
|
14
|
-
| S2 | Workspace/Portable Souls adoption of the OATS repos | ✅
|
|
15
|
-
| S3 | Messaging capability readiness on the new infrastructure (aweb) |
|
|
16
|
-
| S4 | Official capabilities `oats.core` / `oats.setup` + explicit default + onboarding `oats-setup-expert` |
|
|
17
|
-
| S5 | Official marketplace = reviewed list in oats repo | ✅ D4 merged
|
|
18
|
-
| S6 | Five expert souls created in the oats repo (`souls/<name>/`) |
|
|
19
|
-
| S7 | Centralised per-soul knowledge in `oats-knowledge` (migration + PR-only learning) |
|
|
20
|
-
| S8 | Desktop parity (marketplace view, soul creation with `oats.core`, onboarding flow) | ⬜ after
|
|
13
|
+
| S1 | Knowledge capability contract rework (kernel↔provider boundary, OKF 2.x) | ✅ OATS 0.24.1 / OKF 2.1.1 published | P | done for this phase |
|
|
14
|
+
| S2 | Workspace/Portable Souls adoption of the OATS repos | ✅ workspace + seven indexes + six imports · ✅ **0.24.2 published** (onboard verified from the npm tarball) · 🔄 Antares re-run requested · 🔄 five seams → L, 0.24.3 | lead, L, Antares | re-run report; seams PR |
|
|
15
|
+
| S3 | Messaging capability readiness on the new infrastructure (aweb) | ✅ aweb 1.11.0 released · ✅ **catalog + six editions pin v1.11.0 (0.24.2)** · ⬜ second-operator re-run | P, lead | Antares re-run |
|
|
16
|
+
| S4 | Official capabilities `oats.core` / `oats.setup` + explicit default + onboarding `oats-setup-expert` | ✅ D1, D2, **D3 merged (PR35)**: `oats onboard` verified live (acquire 1.1.1 → setup expert with both caps → scaffold composes the five capability skills, no legacy) · `oats.framework` 1.1.1 tagged | P, L | done; Desktop surfaces → S8 |
|
|
17
|
+
| S5 | Official marketplace = reviewed list in oats repo | ✅ D4 merged · ✅ `oats.framework` 1.1.1 listed (`oats.core`, `oats.setup`, `oats.knowledge-theory` aliases) | M | Desktop view → S8 |
|
|
18
|
+
| S6 | Five expert souls created in the oats repo (`souls/<name>/`) | ✅ five + `oats-setup-expert` on main, all declaring `oats.core`, exported + imported | M, L, lead | legacy `agents/` cutover after S7 proof |
|
|
19
|
+
| S7 | Centralised per-soul knowledge in `oats-knowledge` (migration + PR-only learning) | ✅ **repo PUBLIC; PR #1 merged → main 8d67eab4, 25 accepted concepts**, owners = published souls, validator pinned OKF 2.1.1 · 🔄 fresh-reader proof assigned to Juan's side · ⬜ legacy in-soul knowledge decommission | lead, Antares/Juan | fresh-reader + PR-learning proof; then retire `agents/*/soul/knowledge` |
|
|
20
|
+
| S8 | Desktop parity (marketplace view, soul creation with `oats.core`, onboarding flow) | ⬜ after D3 · **host offered: Juan's machine (has `claude`)** — accepted | fresh Desktop engineer on Juan's host | brief + spawn params after D3 |
|
|
21
21
|
|
|
22
22
|
## S1 — Knowledge capability contract rework
|
|
23
23
|
- ✅ Provider-neutral contract, binding wire v1, helper/input contract, retained execution: OATS 0.24.0 + OKF 2.1.0 (f20f8e57) published.
|
|
@@ -28,21 +28,32 @@ Legend: ✅ on main/published · 🔄 in flight (PR/branch) · 🟡 preserved, n
|
|
|
28
28
|
- ✅ **PR23 merged f6d5a89b**: `oats-workspace.yaml` (7 members, `imports: []`), `oats.yaml` (exports souls/oats-expert, oats-package, capabilities/oats-authoring), transitional `souls/oats-expert/` edition, `docs/workspace-adoption.md`, layout tests.
|
|
29
29
|
- ✅ **PR24 merged da38e5a9**: deletion of `skills/oats-portable-setup` + `oats inspect --request` read-only seam (ACCEPTED as the public inspection route); full gate 1621/0.
|
|
30
30
|
- ✅ Member `oats.yaml` merged to main: oats-okf #3 (fec78a20), oats-aweb #1 (069ea2f6), oats-authoring #1 (54183a6a), oats-jira #1 (2f855daf).
|
|
31
|
-
-
|
|
31
|
+
- ✅ oats-dev#1 (main 6e164ee3) and oats-linear#1 (main a2121e48) merged after Juan granted write access — M's exact commits 0434f4ef / 8c183c37.
|
|
32
32
|
- ⬜ `imports:` pin of `souls/oats-expert` at its published revision (after member indexes).
|
|
33
33
|
- ⬜ Fresh local deployment from the shared definition (P1.5) — the real acceptance gate.
|
|
34
34
|
|
|
35
|
+
## S2 — second-operator gate report (Antares, Juan's machine, 2026-09-20)
|
|
36
|
+
Fresh dir, local `@awebai/oats@0.24.1`, no prior state. `inspect --request` → ready-for-preparation, membership eligible, source `souls/oats-kernel-expert@caa341f3`. `prepare` resolved and materialized `oats-package@caa341f3`, `oats.okf@v2.1.1`, `oats.aweb@v1.10.3`, `oats.core`, `oats.setup`, `oats.knowledge-theory` + soul; artifact-set approvals worked. Terminal: `needs-configuration` + `provider-not-qualified` (aweb 1.10.3 has no binding interface) — expected. Seams (assigned to L, one PR, priority):
|
|
37
|
+
1. `inspect --request` requires `workTarget`; `prepare --request` refuses it (`buildFreshPreparationRequest` exists but the CLI never uses it).
|
|
38
|
+
2. `prepare` on the absent deployment inspect blessed → raw `ENOENT` + host path through the JSON envelope.
|
|
39
|
+
3. `prepare` writes lock v3; `oats trust <cap> --dir` rejects it (`unsupported lockfileVersion 3`) → dead end from `--help`.
|
|
40
|
+
4. The working `trust --deployment --artifact-set <sha256>` route is absent from `--help`.
|
|
41
|
+
5. Problems carry `origins: []` and no slot/capability, so a valid and a bogus `stores.oats` binding produce byte-identical output. **Root cause (L's trace):** both OKF `normalize` calls refused because the operator request had no OKF runtime settings (`bindings-file`, `state-dir` — absolute host paths, no defaults); the message never said so. Fix = attribute problems by slot/capability and name the missing item; the identical pair is correct output for that input and stays identical. Guidance for the required settings → P (oats-workspace-setup).
|
|
42
|
+
|
|
35
43
|
## S3 — Messaging (aweb) on the new infrastructure
|
|
44
|
+
- ✅ **aweb PR3 merged → v1.11.0 (93f8ab96)**: `binding {normalize,bind,check}` on the existing wire; `check` = HOME-route operational custody only (explicit private team, `delivery: session`, kernel ≥0.24.2 via caller-owned `OATS_CLI_BIN`, retained `launchSelection` must be input-capable Claude/Codex; strict-Pi print → `needs-configuration`, never downgraded). Native adapter over existing `aw` commands with physical identity-dir custody and redacted tokens. Standalone 30/0; coupling 14/0 vs kernel b92f0d07. PR33 (launchSelection projection, OATS_CLI_BIN in codec env) merged b92f0d07.
|
|
36
45
|
- Facts: released aweb 1.10.3 has no binding interface; broker refuses. aw 1.36.1 broker calls `oats session inspect/input --home H`; never restarts stopped runtime; strict-Pi print mode can't take session input.
|
|
37
46
|
- 🔄 oats-aweb **PR2** codec (165b20e) + uncommitted `lib/captured-execution.mjs` (6/6).
|
|
38
47
|
- ✅ Lead answered (d9d912a4): pilot primary = Pi strict print host explicit model; helper = Pi sole-OKF (Claude/Codex allowed by 2.1.1); authority = existing HOME route + L's custody fix, gated on `oats >=0.24.1`; no new grant mechanism. P delivers aweb 1.11.0 PR.
|
|
39
|
-
-
|
|
48
|
+
- ✅ **PR27 merged (5af848fc)**: HOME-only session route applies existing captured custody; refuses before transport on drift. Full gate 1626/1632 (2 pre-existing env failures reproduced on main). Ships in **v0.24.1** — the kernel floor the aweb adapter gates on.
|
|
40
49
|
|
|
41
50
|
## S4 — `oats.core` / `oats.setup` / onboarding
|
|
51
|
+
- ✅ **D3 merged PR35 (37c5c012)**: `oats onboard` classic local bootstrap; edition `souls/oats-setup-expert` (core+setup, provider defaults `none`, no knowledge owner). Full gate 1639/0. Live: onboard → acquire `oats.framework` 1.1.1 @0aad753c → soul declares both caps at that commit → scaffold-only spawn composes exactly `oats-operate, oats-souls, oats-config, oats-packages, oats-workspace-setup` + the `oats.core` injection, no legacy kernel skills. Baseline hygiene fixed on main (a96f24df).
|
|
52
|
+
- ✅ **D1 merged PR28 (70b10822)**, distribution tag `oats-framework/v1.1.0` on 9930dcfb; **D2 merged PR29 (9930dcfb)** full gate 1634/0. Verified live: `oats create` writes `requires.capabilities.oats.core` with the catalog source; `oats install oats.framework` acquires all three capabilities from the tag.
|
|
42
53
|
- ✅ Decision + plan D1–D4 on main 18af53be; docs reference as accepted-not-shipped.
|
|
43
54
|
- 🔄 **D1** (P, started 16:29Z; package identity confirmed: rename distribution package to `oats.framework` 1.1.0, capabilities 1.0.0, `oats.knowledge-theory` unchanged) package `oats.core` (`oats-operate`, `oats-souls`, oats.md injection) and `oats.setup` (oats-config, oats-packages, adoption guidance) under `oats-package/capabilities/`. Owner P.
|
|
44
55
|
- 🔄 **D2** (L, after custody fix) soul creation writes explicit `requires.capabilities.oats.core`; kernel skill list de-ambiented (one-release coexistence); checked-in souls updated. Owner L.
|
|
45
|
-
-
|
|
56
|
+
- 🔄 **D3** (L, in progress) onboarding creates `oats-setup-expert` (edition in `souls/`); CLI verb **`oats onboard`** — `oats setup` is already the record capture-setup command and stays untouched.
|
|
46
57
|
- Exit: fresh onboarding → running setup expert; created soul shows `oats.core`; kernel ships no ambient operational skill.
|
|
47
58
|
|
|
48
59
|
## S5 — Official marketplace
|
|
@@ -50,21 +61,23 @@ Legend: ✅ on main/published · 🔄 in flight (PR/branch) · 🟡 preserved, n
|
|
|
50
61
|
- ✅ **D4 merged PR26 (786490ae)**: `docs/official-marketplace.md`, `package-catalog.json` policy pointer (inert to the reader), README/packages/capabilities links, D3 sketch in adoption guide. ⬜ entries for `oats.core`/`oats.setup` at D1 release. Desktop view → S8.
|
|
51
62
|
|
|
52
63
|
## S6 — Five expert souls in the oats repo
|
|
64
|
+
- ✅ **PR30 merged (40a579dc)** + maintainer follow-up **caa341f3**: all five declare `oats.core: {source: repo:oats-package}`, oats.okf@v2.1.1; `oats.yaml` exports all five; `oats-workspace.yaml` imports all five at caa341f3 (375b9f42). Live inspection against published main resolves them.
|
|
53
65
|
- Roster (decided): `oats-expert`, `oats-kernel-expert`, `oats-desktop-expert`, `market-research-expert`, `oats-assistant`.
|
|
54
66
|
- 🟡 Candidate: `expert-roster` worktree (b5e233b9 + 519 uncommitted changes: five `agents/<name>/soul/` + legacy roster deletions). Reviewed earlier; NOT committed.
|
|
55
67
|
- ✅ `souls/oats-expert` transitional edition on main already declares owns/reads for the five nodes.
|
|
56
68
|
- 🔄 Assigned to M (17:05Z): create `souls/<name>/` editions for the other four from the candidate; each declares `oats.core` explicitly (S4 rule) + `oats.okf`/`oats.aweb` sources; export in `oats.yaml`. Legacy `agents/` roster retirement is a separate, later cutover.
|
|
57
69
|
|
|
58
70
|
## S7 — Centralised knowledge in `oats-knowledge`
|
|
71
|
+
- ✅ Juan made the repo PUBLIC (2026-09-20). Bootstrap history pushed to main; **PR #1 merged (8d67eab4)**: 25 curated concepts, roadmap re-verified to the 0.24.1 baseline and 2026-09-20 decisions, validator pinned to OKF v2.1.1, strict OKF 25/0/0, ownership tests 24/24.
|
|
59
72
|
- 🟡 Curated corpus: 35 concepts (five nodes) on local `curation/expert-knowledge` in `/Users/pepe-reyero/OATS-workspace/oats-knowledge`, **uncommitted**. Bootstrap + one PR-only harvest already proven on `josep-reyero/oats-knowledge` (3 commits).
|
|
60
73
|
- ⛔ Target `awebai/oats-knowledge` is EMPTY and PRIVATE; **visibility undecided** (stated requirement: public). Human decision needed before publishing.
|
|
61
74
|
- ⬜ Then: push bootstrap + curation as PR to awebai; bind `stores.oats` in the pilot deployment; prove fresh-reader + Git-PR learning with the new souls; retire old in-soul knowledge (`agents/*/soul/knowledge`) as a final cutover.
|
|
62
75
|
|
|
63
76
|
## S8 — Desktop parity
|
|
77
|
+
- Finding (L, D2 audit): the Desktop server has **no soul-creation endpoint** today (roster reads, existing-soul edits/capability operations, instance spawn only). Soul creation with explicit `oats.core`, the marketplace view and the onboarding flow are new Desktop features, not wiring.
|
|
64
78
|
- ⬜ After S4/S5: official marketplace view/search; soul creation showing `oats.core`; onboarding flow; redesign parity vs `Oats UX Redesign and Desktop Discovery (1)`.
|
|
65
79
|
- ⛔ Fresh `oats-desktop-engineer` not spawned: `claude` not on PATH → choose Pi/Codex or install (human).
|
|
66
80
|
|
|
67
81
|
## Blockers needing the human
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
3. Desktop engineer runtime (Claude absent) — gates S8.
|
|
82
|
+
- ~~oats-knowledge visibility~~ → PUBLIC (Juan). ~~oats-dev/oats-linear access~~ → granted, indexes merged. ~~Desktop runtime~~ → Juan's machine hosts the Desktop lane (has `claude`).
|
|
83
|
+
- None open at 23:10Z. Juan's side (Antares) takes: (a) fresh-deployment gate P1.5, (c) fresh-reader proof, (b) Desktop host after D3.
|
|
@@ -9,9 +9,11 @@ owned; production capability/profile readiness is not established by the fixture
|
|
|
9
9
|
|
|
10
10
|
```sh
|
|
11
11
|
oats inspect --request /absolute/inspection.json --json
|
|
12
|
+
# Optional explicit request export (new private file; never overwrite):
|
|
13
|
+
oats inspect --request /absolute/inspection.json --emit-prepare-request /absolute/preparation.json --json
|
|
12
14
|
```
|
|
13
15
|
|
|
14
|
-
This mode accepts
|
|
16
|
+
This mode accepts one request file, optional `--emit-prepare-request`, and `--json`. Explicit captured selectors
|
|
15
17
|
or current-context flags conflict before file reads; inherited captured environment
|
|
16
18
|
is not new-work input. Other existing inspect modes are unchanged. The shared
|
|
17
19
|
bounded strict JSON request reader feeds the existing inspection validator intact:
|
|
@@ -66,21 +68,47 @@ have not been classified by their owner and are omitted. Import summaries expose
|
|
|
66
68
|
`payloadOmitted`. Top-level `omitted:{providerPayloads:true,adoptionValues:true}`
|
|
67
69
|
states that this is a metadata view, not a lossless request or a safe-payload claim.
|
|
68
70
|
It is not an issued `buildFreshPreparationRequest` witness, even in the same
|
|
69
|
-
process.
|
|
71
|
+
process. The opt-in `--emit-prepare-request` route calls that existing builder
|
|
72
|
+
on the real in-process inspection before dropping the private witness. It writes
|
|
73
|
+
only `.preparation` to a new mode-0600 file at an explicit normalized absolute
|
|
74
|
+
path with an existing real parent; existing files/symlinks are refused, never
|
|
75
|
+
overwritten. JSON output names `prepareRequestFile` and records the explicit
|
|
76
|
+
request-file write in `effects`; it does not echo the request contents. The
|
|
77
|
+
export can carry unclassified adoption declarations and must remain private;
|
|
78
|
+
requests must contain nonsecret values or credential references, never secrets.
|
|
79
|
+
A held inspection cannot emit a fresh preparation request. Core callers can
|
|
80
|
+
explicitly request this data via `{includePrepareRequest:true}`; the default
|
|
81
|
+
metadata projection and its omissions are unchanged.
|
|
82
|
+
|
|
83
|
+
The file is reusable new-work input, NOT a stored resolution, approval, admission,
|
|
84
|
+
or serialized ready-inspection permission. Preparation performs fresh validation
|
|
85
|
+
and observations, including re-resolving any mutable source selectors. Provider
|
|
86
|
+
configuration still requires explicit operator choices; conversion invents none.
|
|
70
87
|
|
|
71
88
|
Existing managed deployment state is preserved and reported, not repaired or
|
|
72
89
|
migrated. An absent selected path requires explicit operator provisioning and
|
|
73
|
-
reinspection.
|
|
90
|
+
reinspection. Prepare refuses it with typed `needs-configuration` and provisioning
|
|
91
|
+
guidance before fetching or writing managed state, not a raw ENOENT. Inspection's
|
|
92
|
+
`ready` means the path is eligible for fresh setup, not already provisioned.
|
|
93
|
+
The serialized inspection does not lock the filesystem or authorize
|
|
74
94
|
later mutation; preparation retains its own existing validation/custody rules.
|
|
75
95
|
The inspected work target does not become source identity or an implied placement
|
|
76
96
|
choice. Supported captured directory scaffolds own their separate H/work.
|
|
77
97
|
|
|
78
98
|
## Existing preparation and retained execution
|
|
79
99
|
|
|
80
|
-
`oats prepare --request`
|
|
81
|
-
OR standalone context, operator policy/bindings,
|
|
82
|
-
launch and helperLaunches.
|
|
83
|
-
|
|
100
|
+
`oats prepare --request` accepts deployment/source/origin, optional `workTarget`,
|
|
101
|
+
workspace/member OR standalone context, operator policy/bindings,
|
|
102
|
+
mode/local-input authorization, launch and helperLaunches. The original minimal
|
|
103
|
+
inspection request (without inspection-only `catalogIndexes`) is also accepted;
|
|
104
|
+
use the converter rather than stripping fields from a metadata/result wrapper.
|
|
105
|
+
Explicit `workTarget` is validated with the same physical existing-directory
|
|
106
|
+
validator as inspection and returned as work-context metadata. It takes precedence
|
|
107
|
+
over any caller assumption about cwd: no cwd/config fallback selects its value.
|
|
108
|
+
Omitting it preserves prior preparation behavior without inventing a placement.
|
|
109
|
+
It does not change source identity, `operator.localBase`, work mode, or captured
|
|
110
|
+
H/work placement. Do not pass an inspection result/catalog wrapper or private
|
|
111
|
+
scratch `directory` to preparation. Exact executable approval is separate. A required provider whose binding
|
|
84
112
|
code is unapproved may return `needs-configuration` with an `approval-required`
|
|
85
113
|
problem and exact artifact-set/capability requests, before any record exists:
|
|
86
114
|
|
|
@@ -92,6 +120,44 @@ oats spawn <subject> --deployment <D> --resolution <R> --home <new-H> --no-launc
|
|
|
92
120
|
oats session start --deployment <D> --resolution <R> --home <H> --request /absolute/native.json --json
|
|
93
121
|
```
|
|
94
122
|
|
|
123
|
+
Each `selections[]` row carries an `artifactSet` id and an `approvalRequired[]`
|
|
124
|
+
array of **capability ids**. Pair them: pass the capability to `trust` and that
|
|
125
|
+
row's artifact-set id to `--artifact-set`. These are not interchangeable ids.
|
|
126
|
+
`trust <capability> --dir <D>` against a v3 deployment now refuses with typed
|
|
127
|
+
`needs-configuration` and exact available-set commands; it never picks or approves
|
|
128
|
+
a set automatically. Classic v1/v2 trust remains the classic route.
|
|
129
|
+
|
|
130
|
+
Provider preparation problems carry `slot` and `capability`, plus original
|
|
131
|
+
provenance where available. A no-interface provider is identified with kernel-known
|
|
132
|
+
manifest/version facts. Other supported slots still normalize, resolve through
|
|
133
|
+
the same choice engine, and bind if their own choices are resolved; any required
|
|
134
|
+
slot problem still prevents publication. Provider free text is not passed through.
|
|
135
|
+
Different opaque inputs need not produce different public errors if both fail the
|
|
136
|
+
same provider prerequisite. In particular, missing OKF host runtime settings can
|
|
137
|
+
hold both syntactically valid Git locators; preparation does not test whether a
|
|
138
|
+
remote repository exists. Required readiness checks remain later, with the provider.
|
|
139
|
+
|
|
140
|
+
### Operator input
|
|
141
|
+
|
|
142
|
+
When present, `operator` requires both `policy` (object; `{}` is valid) and
|
|
143
|
+
`document` (`{ "kind": "operator", "id": "setup-attempt" }`). Its ONLY optional
|
|
144
|
+
fields are `localBase`, `allowLocalPaths`, `sourceContext`, and `bindings`:
|
|
145
|
+
|
|
146
|
+
- `policy`: explicit provider/additive selections with their selected sources and
|
|
147
|
+
settings, using the existing policy grammar. It cannot erase soul requirements.
|
|
148
|
+
- `localBase`: explicit absolute base for relative local policy sources. Work
|
|
149
|
+
context/cwd is not a substitute.
|
|
150
|
+
- `allowLocalPaths`: explicit boolean authorization for those local policy sources.
|
|
151
|
+
Top-level local acquisition authorization remains a separate input.
|
|
152
|
+
- `sourceContext`: existing qualified repository anchor for `repo:` policy sources;
|
|
153
|
+
not a new repository inferred from workTarget.
|
|
154
|
+
- `bindings`: provider-owned map. Kernel preserves it and its document pointers;
|
|
155
|
+
it does not interpret store names, Git destinations, credentials or private teams.
|
|
156
|
+
|
|
157
|
+
Selecting an inherited store does not replace required provider runtime settings.
|
|
158
|
+
Use the selected provider's instructions for those settings; kernel must not guess
|
|
159
|
+
host-owned durable paths or copy native authentication.
|
|
160
|
+
|
|
95
161
|
Repreparation after explicit approval is ordinary continuation in the selected,
|
|
96
162
|
now-managed deployment; do not delete its state to make fresh preflight pass.
|
|
97
163
|
Required hooks still run under their admitted custody with `--no-launch`; a parsed
|
package/docs/first-team.md
CHANGED
|
@@ -42,6 +42,48 @@ For several repositories initialize their common workspace, then select the
|
|
|
42
42
|
repository owning the soul with `--dir /path/to/workspace/project` for
|
|
43
43
|
create/spawn/retire. A team roster does not select a work repository for spawn.
|
|
44
44
|
|
|
45
|
+
## Onboarding with the setup expert
|
|
46
|
+
|
|
47
|
+
For a kernel build that includes `oats onboard` (check `oats onboard --help`),
|
|
48
|
+
start in an explicit empty deployment:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
oats onboard --dir /absolute/new-deployment --json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This command is **not present in the published 0.24.0/0.24.1 kernels**. It is a
|
|
55
|
+
classic local bootstrap, not captured preparation or workspace enrollment. It
|
|
56
|
+
acquires `oats.framework` from the official catalog, exact-locks its artifacts,
|
|
57
|
+
selects only `oats.core` and `oats.setup` for the new local `oats-setup-expert`,
|
|
58
|
+
and prints the exact next spawn command. Review and run the returned
|
|
59
|
+
`result.next.command` when ready; it addresses this same kernel and deployment.
|
|
60
|
+
Onboarding itself never launches a model, changes native authentication or
|
|
61
|
+
installs capture hooks/services. **`oats setup` remains the separate record
|
|
62
|
+
capture-setup command**, not an alias for onboarding.
|
|
63
|
+
|
|
64
|
+
The expert receives `oats-operate`, `oats-souls`, `oats-config`, `oats-packages`
|
|
65
|
+
and `oats-workspace-setup`, without duplicate legacy kernel skill copies. It has
|
|
66
|
+
no hard knowledge/messaging dependency, so it can help select and configure those
|
|
67
|
+
providers afterward. Catalog identity grants no executable trust: the bootstrap
|
|
68
|
+
uses resource-only core/setup capabilities and refuses unexpected executable
|
|
69
|
+
surfaces instead of auto-approving them.
|
|
70
|
+
|
|
71
|
+
An existing roster is refused unless `--force-existing` is explicit. That flag
|
|
72
|
+
permits adding the new soul, not overwriting an existing setup expert or disabling
|
|
73
|
+
providers for other souls. Failures report partial acquisition/creation rather
|
|
74
|
+
than claiming atomic captured preparation. Preserve that evidence before retrying.
|
|
75
|
+
|
|
76
|
+
Optional `--workspace git:host/org/repository[@revision]` reads the selected
|
|
77
|
+
repository through ordinary discovery: use its pinned `oats-setup-expert` import
|
|
78
|
+
when present, otherwise its own advertised `souls/oats-setup-expert` edition at
|
|
79
|
+
the observed revision. Missing or incompatible explicit sources refuse; they do
|
|
80
|
+
not fall back to the packaged default. The copied edition's package must match
|
|
81
|
+
the official acquisition; workspace policy, teams and provider adoption values
|
|
82
|
+
are not silently adopted. Without this option, only the packaged definition and
|
|
83
|
+
instruction text are used—no knowledge corpus is bundled.
|
|
84
|
+
|
|
85
|
+
The manual path below retains its stated older integration/version scope.
|
|
86
|
+
|
|
45
87
|
## Configure explicit knowledge and optional messaging
|
|
46
88
|
|
|
47
89
|
Edit the existing entries in `oats-config.yaml`; do not append a second
|
package/docs/layers.md
CHANGED
|
@@ -80,7 +80,7 @@ Messaging is conversation, not automatically task state. Accepted knowledge may
|
|
|
80
80
|
|
|
81
81
|
The current slot name is **`messaging`**. The capability owns native identity, addressing, team membership, transport, wake delivery and qualification. A team alias in a workspace is a declaration, not proof that an actor is enrolled or a privacy property is enforced.
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
aweb 1.10.3 supports its legacy setup/lifecycle path but lacks the captured provider-binding interface. **aweb 1.11.0** (OATS >=0.24.2) adds it: `check` qualifies HOME-route operational custody for an input-capable Claude/Codex primary with an explicit private team and `delivery: session`; a strict-Pi print primary reports `needs-configuration` rather than dropping the requirement. Qualification is not account delegation, broker delivery or model consumption.
|
|
84
84
|
|
|
85
85
|
The earlier proposed `reach` ladder is **not an enforced universal field**. In particular, aweb's `team_and_contacts` includes verified same-team senders; the compatibility spellings `contacts-only` and `contacts_only` do not establish owner-only admission. A config command succeeding proves neither inbound/outbound restrictions nor knowledge visibility. See the [identity/membership amendment](design/2026-09-08-expert-assisted-deployment-proposal.md#membership-reach-and-visibility-are-separate) and [messaging boundary](design/2026-09-16-messaging-capability-contract.md).
|
|
86
86
|
|
|
@@ -58,17 +58,22 @@ or workspace membership alone does not make a package official.
|
|
|
58
58
|
Contact and license evidence may live in the package/repository documentation;
|
|
59
59
|
this policy does not invent new catalog or manifest fields.
|
|
60
60
|
|
|
61
|
-
##
|
|
61
|
+
## Listed first set
|
|
62
62
|
|
|
63
|
-
-
|
|
64
|
-
`oats.linear`, `oats.dev` and `oats.
|
|
65
|
-
- **
|
|
66
|
-
`oats
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
- Listed capabilities: `oats.okf`, `oats.aweb`, `oats.authoring`, `oats.jira`,
|
|
64
|
+
`oats.linear`, `oats.dev`, `oats.knowledge-theory`, `oats.core` and `oats.setup`.
|
|
65
|
+
- **`oats.framework` 1.1.1** is listed at tag `oats-framework/v1.1.1` in
|
|
66
|
+
`awebai/oats`, payload root `oats-package`. The `oats.core`, `oats.setup` and
|
|
67
|
+
`oats.knowledge-theory` aliases select that distribution; package identity is
|
|
68
|
+
distinct from capability identity. Core supplies operation/soul guidance;
|
|
69
|
+
setup supplies OATS Soul Setup, configuration and package guidance.
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
These entries are in the current repository catalog. An older installed CLI keeps
|
|
72
|
+
its bundled catalog; publication here does not update that installation or rewrite
|
|
73
|
+
old source references, locks or tags. Follow that CLI's supported acquisition path.
|
|
74
|
+
The [workspace adoption guide](workspace-adoption.md) distinguishes the published
|
|
75
|
+
capabilities and five expert imports from the still-pending D3 setup-expert flow.
|
|
76
|
+
No package is silently added to an existing soul.
|
|
72
77
|
|
|
73
78
|
## Updates, deprecation and removal
|
|
74
79
|
|
package/docs/packages.md
CHANGED
|
@@ -402,7 +402,7 @@ sources; installing a kernel does not advance existing package locks:
|
|
|
402
402
|
{
|
|
403
403
|
"packages": {
|
|
404
404
|
"oats.okf": { "url": "https://github.com/awebai/oats-okf.git", "ref": "v2.0.0", "path": "oats-package" },
|
|
405
|
-
"oats.
|
|
405
|
+
"oats.framework": { "url": "https://github.com/awebai/oats.git", "ref": "oats-framework/v1.1.1", "path": "oats-package" },
|
|
406
406
|
"oats.dev": { "url": "https://github.com/awebai/oats-dev.git", "ref": "v1.0.0", "path": "oats-package" }
|
|
407
407
|
},
|
|
408
408
|
"capabilities": { "oats.review": "oats.dev" }
|
|
@@ -427,13 +427,17 @@ npm drops the source worker soul's `CLAUDE.md -> AGENTS.md`. It must not be
|
|
|
427
427
|
advertised as a complete local package or repaired after acquisition to evade
|
|
428
428
|
integrity checks. Git transport preserves the canonical source alias.
|
|
429
429
|
|
|
430
|
-
The
|
|
430
|
+
The `oats.framework` distribution package is a separate Git payload in this
|
|
431
431
|
repository's `oats-package/`, excluded from the kernel npm tarball. The catalog
|
|
432
|
-
entry selects published framework
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
432
|
+
entry selects the published `oats-framework/v1.1.1` tag, which exports three
|
|
433
|
+
capabilities: `oats.core` (day-to-day operation: `oats-operate`, `oats-souls`
|
|
434
|
+
and the "you run on OATS" briefing — declared explicitly on every soul by
|
|
435
|
+
default at creation and removable), `oats.setup` (OATS Soul Setup: `oats-config`,
|
|
436
|
+
`oats-packages`, `oats-workspace-setup`) and the optional `oats.knowledge-theory`
|
|
437
|
+
(authoring skill and `knowledge-theory-expert`). Acquire it with
|
|
438
|
+
`oats install oats.framework`; the capability ids also resolve through the
|
|
439
|
+
catalog aliases. Acquiring it does not activate anything, bind a knowledge
|
|
440
|
+
layer or add a runtime judge.
|
|
437
441
|
|
|
438
442
|
Updating OKF v1 to v2 is a breaking capability change. Preserve existing
|
|
439
443
|
knowledge and source state/cursors, explicitly bind/provision external owners,
|