@phamvuhoang/otto-core 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-help.d.ts +18 -0
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +32 -1
- package/dist/cli-help.js.map +1 -1
- package/dist/fanout.d.ts +56 -0
- package/dist/fanout.d.ts.map +1 -0
- package/dist/fanout.js +119 -0
- package/dist/fanout.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/journal-config.d.ts +9 -0
- package/dist/journal-config.d.ts.map +1 -0
- package/dist/journal-config.js +31 -0
- package/dist/journal-config.js.map +1 -0
- package/dist/journal-gate.d.ts +46 -0
- package/dist/journal-gate.d.ts.map +1 -0
- package/dist/journal-gate.js +135 -0
- package/dist/journal-gate.js.map +1 -0
- package/dist/journal-ledger.d.ts +13 -0
- package/dist/journal-ledger.d.ts.map +1 -0
- package/dist/journal-ledger.js +33 -0
- package/dist/journal-ledger.js.map +1 -0
- package/dist/journal-source.d.ts +19 -0
- package/dist/journal-source.d.ts.map +1 -0
- package/dist/journal-source.js +38 -0
- package/dist/journal-source.js.map +1 -0
- package/dist/journal.d.ts +46 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +158 -0
- package/dist/journal.js.map +1 -0
- package/dist/loop.d.ts +13 -0
- package/dist/loop.d.ts.map +1 -1
- package/dist/loop.js +91 -7
- package/dist/loop.js.map +1 -1
- package/dist/model-tier.d.ts +69 -0
- package/dist/model-tier.d.ts.map +1 -0
- package/dist/model-tier.js +101 -0
- package/dist/model-tier.js.map +1 -0
- package/dist/plan-tasks.d.ts +44 -0
- package/dist/plan-tasks.d.ts.map +1 -0
- package/dist/plan-tasks.js +167 -0
- package/dist/plan-tasks.js.map +1 -0
- package/dist/run-bin.d.ts.map +1 -1
- package/dist/run-bin.js +21 -1
- package/dist/run-bin.js.map +1 -1
- package/dist/runner.d.ts +18 -14
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +12 -23
- package/dist/runner.js.map +1 -1
- package/dist/stage-exec.d.ts +13 -0
- package/dist/stage-exec.d.ts.map +1 -1
- package/dist/stage-exec.js +32 -1
- package/dist/stage-exec.js.map +1 -1
- package/dist/stages.d.ts +28 -0
- package/dist/stages.d.ts.map +1 -1
- package/dist/stages.js +30 -0
- package/dist/stages.js.map +1 -1
- package/dist/threads-api.d.ts +46 -0
- package/dist/threads-api.d.ts.map +1 -0
- package/dist/threads-api.js +101 -0
- package/dist/threads-api.js.map +1 -0
- package/dist/worktree.d.ts +24 -0
- package/dist/worktree.d.ts.map +1 -0
- package/dist/worktree.js +43 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +1 -1
- package/templates/journal-screen.md +19 -0
- package/templates/journal-write.md +16 -0
- package/templates/plan.md +26 -4
- package/templates/subtask.md +32 -0
package/dist/stage-exec.js
CHANGED
|
@@ -4,10 +4,18 @@ import { DEFAULT_AGENT } from "./agent-runtime.js";
|
|
|
4
4
|
import { analyzeContext } from "./context-report.js";
|
|
5
5
|
import { applyPromptReduction } from "./prompt-reduction.js";
|
|
6
6
|
import { renderTemplate } from "./render.js";
|
|
7
|
+
import { resolveStageModel } from "./model-tier.js";
|
|
7
8
|
import { DEFAULT_BACKOFF_MS, backoffFor, withRetries } from "./retry.js";
|
|
8
9
|
import { getAgentRuntime, runStage, stageLogPath, } from "./runner.js";
|
|
9
10
|
import { readSafetyPolicy, } from "./safety-policy.js";
|
|
10
11
|
import { USE_COLOR, dim } from "./stream-render.js";
|
|
12
|
+
/** Fallback ladder when routing is requested without one — every tier resolves
|
|
13
|
+
* to the runtime default (issue #66 P11). The real ladder comes from run-bin. */
|
|
14
|
+
const EMPTY_LADDER = {
|
|
15
|
+
cheap: undefined,
|
|
16
|
+
mid: undefined,
|
|
17
|
+
strong: undefined,
|
|
18
|
+
};
|
|
11
19
|
/** A policy violation found at a shell/@spill tag becomes a `blocked` trajectory
|
|
12
20
|
* safety event — the command was denied and skipped, so Otto prevented it. */
|
|
13
21
|
function violationToSafetyEvent(v) {
|
|
@@ -50,12 +58,35 @@ export async function executeStage(opts) {
|
|
|
50
58
|
const { originalChars, reducedChars, cacheHits } = reduced.stats;
|
|
51
59
|
process.stderr.write(`${dim(`prompt reduce ${originalChars} -> ${reducedChars} chars | cache hits ${cacheHits}`)}\n`);
|
|
52
60
|
}
|
|
53
|
-
|
|
61
|
+
// Route the model for this stage (issue #66 P11): a pin wins, else the
|
|
62
|
+
// declared tier through the ladder when routing is on, else runtime default.
|
|
63
|
+
const model = resolveStageModel({
|
|
64
|
+
runtimeId: opts.agentId ?? DEFAULT_AGENT,
|
|
65
|
+
stage,
|
|
66
|
+
routing: opts.modelRouting === true,
|
|
67
|
+
ladder: opts.tierLadder ?? EMPTY_LADDER,
|
|
68
|
+
assessment: opts.riskAssessment,
|
|
69
|
+
escalations: opts.escalations,
|
|
70
|
+
});
|
|
71
|
+
const result = await runStage(stage, prompt, workspaceDir, iteration, spillHostDir, stageLog, {
|
|
72
|
+
signal,
|
|
73
|
+
runtime,
|
|
74
|
+
sink: opts.sink,
|
|
75
|
+
modelSpec: model.spec,
|
|
76
|
+
sandboxWriteRoots: opts.sandboxWriteRoots,
|
|
77
|
+
});
|
|
54
78
|
// Attribute the *final* prompt's window footprint by category (issue #62
|
|
55
79
|
// P7). `prompt` is post-reduction, so the breakdown reflects what was sent.
|
|
56
80
|
return {
|
|
57
81
|
...result,
|
|
58
82
|
contextBreakdown: analyzeContext(prompt),
|
|
83
|
+
...(model.tier
|
|
84
|
+
? {
|
|
85
|
+
routedTier: model.tier,
|
|
86
|
+
routedModel: model.spec,
|
|
87
|
+
modelSource: model.source,
|
|
88
|
+
}
|
|
89
|
+
: {}),
|
|
59
90
|
...(violations.length > 0
|
|
60
91
|
? { safetyEvents: violations.map(violationToSafetyEvent) }
|
|
61
92
|
: {}),
|
package/dist/stage-exec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage-exec.js","sourceRoot":"","sources":["../src/stage-exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EACL,eAAe,EACf,QAAQ,EACR,YAAY,GAEb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,GAEjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"stage-exec.js","sourceRoot":"","sources":["../src/stage-exec.ts"],"names":[],"mappings":"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"}
|
package/dist/stages.d.ts
CHANGED
|
@@ -1,53 +1,81 @@
|
|
|
1
|
+
import type { ModelTier } from "./model-tier.js";
|
|
1
2
|
export type Stage = {
|
|
2
3
|
name: string;
|
|
3
4
|
template: string;
|
|
4
5
|
permissionMode?: string;
|
|
6
|
+
/** Difficulty tier for model routing (issue #66 P11). Absent ⇒ runtime default model. */
|
|
7
|
+
tier?: ModelTier;
|
|
5
8
|
};
|
|
6
9
|
export declare const STAGES: {
|
|
7
10
|
plan: {
|
|
8
11
|
name: string;
|
|
9
12
|
template: string;
|
|
10
13
|
permissionMode: string;
|
|
14
|
+
tier: "strong";
|
|
11
15
|
};
|
|
12
16
|
implementer: {
|
|
13
17
|
name: string;
|
|
14
18
|
template: string;
|
|
15
19
|
permissionMode: string;
|
|
20
|
+
tier: "mid";
|
|
16
21
|
};
|
|
17
22
|
ghafkImplementer: {
|
|
18
23
|
name: string;
|
|
19
24
|
template: string;
|
|
20
25
|
permissionMode: string;
|
|
26
|
+
tier: "mid";
|
|
21
27
|
};
|
|
22
28
|
ghafkIssueImplementer: {
|
|
23
29
|
name: string;
|
|
24
30
|
template: string;
|
|
25
31
|
permissionMode: string;
|
|
32
|
+
tier: "mid";
|
|
26
33
|
};
|
|
27
34
|
linearImplementer: {
|
|
28
35
|
name: string;
|
|
29
36
|
template: string;
|
|
30
37
|
permissionMode: string;
|
|
38
|
+
tier: "mid";
|
|
31
39
|
};
|
|
32
40
|
linearIssueImplementer: {
|
|
33
41
|
name: string;
|
|
34
42
|
template: string;
|
|
35
43
|
permissionMode: string;
|
|
44
|
+
tier: "mid";
|
|
36
45
|
};
|
|
37
46
|
verifier: {
|
|
38
47
|
name: string;
|
|
39
48
|
template: string;
|
|
40
49
|
permissionMode: string;
|
|
50
|
+
tier: "strong";
|
|
41
51
|
};
|
|
42
52
|
applyReviewImplementer: {
|
|
43
53
|
name: string;
|
|
44
54
|
template: string;
|
|
45
55
|
permissionMode: string;
|
|
56
|
+
tier: "strong";
|
|
46
57
|
};
|
|
47
58
|
reviewer: {
|
|
48
59
|
name: string;
|
|
49
60
|
template: string;
|
|
50
61
|
permissionMode: string;
|
|
62
|
+
tier: "strong";
|
|
63
|
+
};
|
|
64
|
+
subImplementer: {
|
|
65
|
+
name: string;
|
|
66
|
+
template: string;
|
|
67
|
+
permissionMode: string;
|
|
68
|
+
tier: "mid";
|
|
69
|
+
};
|
|
70
|
+
journalWrite: {
|
|
71
|
+
name: string;
|
|
72
|
+
template: string;
|
|
73
|
+
permissionMode: string;
|
|
74
|
+
};
|
|
75
|
+
journalScreen: {
|
|
76
|
+
name: string;
|
|
77
|
+
template: string;
|
|
78
|
+
permissionMode: string;
|
|
51
79
|
};
|
|
52
80
|
};
|
|
53
81
|
//# sourceMappingURL=stages.d.ts.map
|
package/dist/stages.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stages.d.ts","sourceRoot":"","sources":["../src/stages.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"stages.d.ts","sourceRoot":"","sources":["../src/stages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yFAAyF;IACzF,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,CAAC;AAOF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8ElB,CAAC"}
|
package/dist/stages.js
CHANGED
|
@@ -10,46 +10,76 @@ export const STAGES = {
|
|
|
10
10
|
name: "plan",
|
|
11
11
|
template: "plan.md",
|
|
12
12
|
permissionMode: "bypassPermissions",
|
|
13
|
+
tier: "strong",
|
|
13
14
|
},
|
|
14
15
|
implementer: {
|
|
15
16
|
name: "implementer",
|
|
16
17
|
template: "afk.md",
|
|
17
18
|
permissionMode: "bypassPermissions",
|
|
19
|
+
tier: "mid",
|
|
18
20
|
},
|
|
19
21
|
ghafkImplementer: {
|
|
20
22
|
name: "ghafk-implementer",
|
|
21
23
|
template: "ghafk.md",
|
|
22
24
|
permissionMode: "bypassPermissions",
|
|
25
|
+
tier: "mid",
|
|
23
26
|
},
|
|
24
27
|
ghafkIssueImplementer: {
|
|
25
28
|
name: "ghafk-issue-implementer",
|
|
26
29
|
template: "ghafk-issue.md",
|
|
27
30
|
permissionMode: "bypassPermissions",
|
|
31
|
+
tier: "mid",
|
|
28
32
|
},
|
|
29
33
|
linearImplementer: {
|
|
30
34
|
name: "linear-implementer",
|
|
31
35
|
template: "linearafk.md",
|
|
32
36
|
permissionMode: "bypassPermissions",
|
|
37
|
+
tier: "mid",
|
|
33
38
|
},
|
|
34
39
|
linearIssueImplementer: {
|
|
35
40
|
name: "linear-issue-implementer",
|
|
36
41
|
template: "linearafk-issue.md",
|
|
37
42
|
permissionMode: "bypassPermissions",
|
|
43
|
+
tier: "mid",
|
|
38
44
|
},
|
|
39
45
|
verifier: {
|
|
40
46
|
name: "verifier",
|
|
41
47
|
template: "verify.md",
|
|
42
48
|
permissionMode: "bypassPermissions",
|
|
49
|
+
tier: "strong",
|
|
43
50
|
},
|
|
44
51
|
applyReviewImplementer: {
|
|
45
52
|
name: "apply-review-implementer",
|
|
46
53
|
template: "apply-review.md",
|
|
47
54
|
permissionMode: "bypassPermissions",
|
|
55
|
+
tier: "strong",
|
|
48
56
|
},
|
|
49
57
|
reviewer: {
|
|
50
58
|
name: "reviewer",
|
|
51
59
|
template: "review.md",
|
|
52
60
|
permissionMode: "bypassPermissions",
|
|
61
|
+
tier: "strong",
|
|
62
|
+
},
|
|
63
|
+
// One fanned-out plan task, run in an isolated worktree with bounded context
|
|
64
|
+
// (issue #66 P11). Mechanical-to-moderate per-task work → mid tier.
|
|
65
|
+
subImplementer: {
|
|
66
|
+
name: "sub-implementer",
|
|
67
|
+
template: "subtask.md",
|
|
68
|
+
permissionMode: "bypassPermissions",
|
|
69
|
+
tier: "mid",
|
|
70
|
+
},
|
|
71
|
+
// P12 public journal (issue #67): generate a generic field note from a memory
|
|
72
|
+
// learning, and adversarially screen a candidate note for leaks. Both produce
|
|
73
|
+
// only text — the harness owns the secrecy gate and the actual posting.
|
|
74
|
+
journalWrite: {
|
|
75
|
+
name: "journal-write",
|
|
76
|
+
template: "journal-write.md",
|
|
77
|
+
permissionMode: "bypassPermissions",
|
|
78
|
+
},
|
|
79
|
+
journalScreen: {
|
|
80
|
+
name: "journal-screen",
|
|
81
|
+
template: "journal-screen.md",
|
|
82
|
+
permissionMode: "bypassPermissions",
|
|
53
83
|
},
|
|
54
84
|
};
|
|
55
85
|
//# sourceMappingURL=stages.js.map
|
package/dist/stages.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stages.js","sourceRoot":"","sources":["../src/stages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stages.js","sourceRoot":"","sources":["../src/stages.ts"],"names":[],"mappings":"AAUA,gFAAgF;AAChF,8EAA8E;AAC9E,iFAAiF;AACjF,kFAAkF;AAClF,gFAAgF;AAChF,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,yEAAyE;IACzE,4EAA4E;IAC5E,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,SAAS;QACnB,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,QAAQ;KACC;IACjB,WAAW,EAAE;QACX,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,QAAQ;QAClB,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,KAAK;KACI;IACjB,gBAAgB,EAAE;QAChB,IAAI,EAAE,mBAAmB;QACzB,QAAQ,EAAE,UAAU;QACpB,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,KAAK;KACI;IACjB,qBAAqB,EAAE;QACrB,IAAI,EAAE,yBAAyB;QAC/B,QAAQ,EAAE,gBAAgB;QAC1B,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,KAAK;KACI;IACjB,iBAAiB,EAAE;QACjB,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,cAAc;QACxB,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,KAAK;KACI;IACjB,sBAAsB,EAAE;QACtB,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,oBAAoB;QAC9B,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,KAAK;KACI;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,WAAW;QACrB,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,QAAQ;KACC;IACjB,sBAAsB,EAAE;QACtB,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,iBAAiB;QAC3B,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,QAAQ;KACC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,WAAW;QACrB,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,QAAQ;KACC;IACjB,6EAA6E;IAC7E,oEAAoE;IACpE,cAAc,EAAE;QACd,IAAI,EAAE,iBAAiB;QACvB,QAAQ,EAAE,YAAY;QACtB,cAAc,EAAE,mBAAmB;QACnC,IAAI,EAAE,KAAK;KACI;IACjB,8EAA8E;IAC9E,8EAA8E;IAC9E,wEAAwE;IACxE,YAAY,EAAE;QACZ,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,kBAAkB;QAC5B,cAAc,EAAE,mBAAmB;KACpB;IACjB,aAAa,EAAE;QACb,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,mBAAmB;QAC7B,cAAc,EAAE,mBAAmB;KACpB;CAClB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threads (Meta) publishing client for the P12 public journal (issue #67).
|
|
3
|
+
* Mirrors linear-api.ts: injectable fetch + credentials from env or
|
|
4
|
+
* ~/.config/otto/threads.json. The Threads Graph API publishes in two steps —
|
|
5
|
+
* create a TEXT container, then publish it.
|
|
6
|
+
*/
|
|
7
|
+
export type ThreadsAuth = {
|
|
8
|
+
token: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
source: string;
|
|
11
|
+
};
|
|
12
|
+
export type ThreadsAuthDeps = {
|
|
13
|
+
env: NodeJS.ProcessEnv;
|
|
14
|
+
readFile: (path: string) => string | null;
|
|
15
|
+
home: string;
|
|
16
|
+
};
|
|
17
|
+
/** Canonical location of the stored Threads credentials (outside any repo). */
|
|
18
|
+
export declare function threadsConfigPath(home: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a Threads token + user id with precedence `OTTO_THREADS_TOKEN` +
|
|
21
|
+
* `OTTO_THREADS_USER_ID` → `~/.config/otto/threads.json` (`{ token, userId }`).
|
|
22
|
+
* Returns null when no source yields both a token and a user id.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveThreadsAuth(deps?: ThreadsAuthDeps): ThreadsAuth | null;
|
|
25
|
+
export type ThreadsErrorKind = "auth" | "network" | "api";
|
|
26
|
+
export declare class ThreadsApiError extends Error {
|
|
27
|
+
kind: ThreadsErrorKind;
|
|
28
|
+
constructor(message: string, kind: ThreadsErrorKind);
|
|
29
|
+
}
|
|
30
|
+
export type ThreadsClient = {
|
|
31
|
+
publish(text: string): Promise<{
|
|
32
|
+
id: string;
|
|
33
|
+
}>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Create a Threads client. The two-step publish: create a TEXT container
|
|
37
|
+
* (`/{userId}/threads`), then publish it (`/{userId}/threads_publish`). `fetch`
|
|
38
|
+
* is injectable for tests; errors are classified as auth/network/api.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createThreadsClient(opts: {
|
|
41
|
+
token: string;
|
|
42
|
+
userId: string;
|
|
43
|
+
fetch?: typeof fetch;
|
|
44
|
+
baseUrl?: string;
|
|
45
|
+
}): ThreadsClient;
|
|
46
|
+
//# sourceMappingURL=threads-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threads-api.d.ts","sourceRoot":"","sources":["../src/threads-api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,MAAM,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC1C,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAcF,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,GAAE,eAAiC,GACtC,WAAW,GAAG,IAAI,CAuBpB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC;AAE1D,qBAAa,eAAgB,SAAQ,KAAK;IACxC,IAAI,EAAE,gBAAgB,CAAC;gBACX,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB;CAKpD;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC;AAI/E;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,aAAa,CAoChB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threads (Meta) publishing client for the P12 public journal (issue #67).
|
|
3
|
+
* Mirrors linear-api.ts: injectable fetch + credentials from env or
|
|
4
|
+
* ~/.config/otto/threads.json. The Threads Graph API publishes in two steps —
|
|
5
|
+
* create a TEXT container, then publish it.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
const defaultAuthDeps = {
|
|
11
|
+
env: process.env,
|
|
12
|
+
readFile: (p) => {
|
|
13
|
+
try {
|
|
14
|
+
return readFileSync(p, "utf8");
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
home: homedir(),
|
|
21
|
+
};
|
|
22
|
+
/** Canonical location of the stored Threads credentials (outside any repo). */
|
|
23
|
+
export function threadsConfigPath(home) {
|
|
24
|
+
return join(home, ".config", "otto", "threads.json");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolve a Threads token + user id with precedence `OTTO_THREADS_TOKEN` +
|
|
28
|
+
* `OTTO_THREADS_USER_ID` → `~/.config/otto/threads.json` (`{ token, userId }`).
|
|
29
|
+
* Returns null when no source yields both a token and a user id.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveThreadsAuth(deps = defaultAuthDeps) {
|
|
32
|
+
const token = deps.env.OTTO_THREADS_TOKEN?.trim();
|
|
33
|
+
const userId = deps.env.OTTO_THREADS_USER_ID?.trim();
|
|
34
|
+
if (token && userId)
|
|
35
|
+
return { token, userId, source: "env" };
|
|
36
|
+
const path = threadsConfigPath(deps.home);
|
|
37
|
+
const raw = deps.readFile(path);
|
|
38
|
+
if (raw != null) {
|
|
39
|
+
try {
|
|
40
|
+
const o = JSON.parse(raw);
|
|
41
|
+
if (typeof o.token === "string" &&
|
|
42
|
+
o.token.trim() &&
|
|
43
|
+
typeof o.userId === "string" &&
|
|
44
|
+
o.userId.trim()) {
|
|
45
|
+
return { token: o.token.trim(), userId: o.userId.trim(), source: path };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// malformed → no credential from this source
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
export class ThreadsApiError extends Error {
|
|
55
|
+
kind;
|
|
56
|
+
constructor(message, kind) {
|
|
57
|
+
super(message);
|
|
58
|
+
this.name = "ThreadsApiError";
|
|
59
|
+
this.kind = kind;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const DEFAULT_BASE = "https://graph.threads.net/v1.0";
|
|
63
|
+
/**
|
|
64
|
+
* Create a Threads client. The two-step publish: create a TEXT container
|
|
65
|
+
* (`/{userId}/threads`), then publish it (`/{userId}/threads_publish`). `fetch`
|
|
66
|
+
* is injectable for tests; errors are classified as auth/network/api.
|
|
67
|
+
*/
|
|
68
|
+
export function createThreadsClient(opts) {
|
|
69
|
+
const fetchImpl = opts.fetch ?? fetch;
|
|
70
|
+
const base = opts.baseUrl ?? DEFAULT_BASE;
|
|
71
|
+
if (!opts.token || !opts.userId) {
|
|
72
|
+
throw new ThreadsApiError("missing Threads credentials", "auth");
|
|
73
|
+
}
|
|
74
|
+
const post = async (url) => {
|
|
75
|
+
let res;
|
|
76
|
+
try {
|
|
77
|
+
res = await fetchImpl(url, { method: "POST" });
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
throw new ThreadsApiError(`Threads request failed: ${e.message}`, "network");
|
|
81
|
+
}
|
|
82
|
+
if (!res.ok) {
|
|
83
|
+
throw new ThreadsApiError(`Threads API returned ${res.status}`, "api");
|
|
84
|
+
}
|
|
85
|
+
const json = (await res.json());
|
|
86
|
+
if (typeof json.id !== "string") {
|
|
87
|
+
throw new ThreadsApiError("Threads API response missing id", "api");
|
|
88
|
+
}
|
|
89
|
+
return { id: json.id };
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
async publish(text) {
|
|
93
|
+
const tok = encodeURIComponent(opts.token);
|
|
94
|
+
const create = `${base}/${opts.userId}/threads?media_type=TEXT&text=${encodeURIComponent(text)}&access_token=${tok}`;
|
|
95
|
+
const { id: creationId } = await post(create);
|
|
96
|
+
const publish = `${base}/${opts.userId}/threads_publish?creation_id=${encodeURIComponent(creationId)}&access_token=${tok}`;
|
|
97
|
+
return post(publish);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=threads-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threads-api.js","sourceRoot":"","sources":["../src/threads-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git-worktree isolation for sub-agent fan-out (issue #66 P11). Each parallel
|
|
3
|
+
* sub-agent runs in its own worktree under `.otto-tmp/wt/<id>` — a separate
|
|
4
|
+
* working directory sharing the repo's object store, so the agents never clobber
|
|
5
|
+
* each other's files. The dir is inside the workspace, so the native OS sandbox
|
|
6
|
+
* still confines writes. `.otto-tmp/` is already gitignored.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Create an isolated worktree at HEAD under `.otto-tmp/wt/<id>`. `--detach` so
|
|
10
|
+
* the sub-agent commits onto a detached HEAD without creating or moving a branch.
|
|
11
|
+
* `cleanup()` removes the worktree (and its dir); it is idempotent and safe to
|
|
12
|
+
* call from a `finally`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createWorktree(workspaceDir: string, id: string): {
|
|
15
|
+
dir: string;
|
|
16
|
+
cleanup: () => void;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Prune leftover worktrees from a crashed prior run: remove the `.otto-tmp/wt`
|
|
20
|
+
* tree wholesale, then GC git's worktree registry so the stale entries don't
|
|
21
|
+
* linger. Call once before a fan-out round.
|
|
22
|
+
*/
|
|
23
|
+
export declare function reapWorktrees(workspaceDir: string): void;
|
|
24
|
+
//# sourceMappingURL=worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../src/worktree.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,MAAM,GACT;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAetC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAGxD"}
|
package/dist/worktree.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git-worktree isolation for sub-agent fan-out (issue #66 P11). Each parallel
|
|
3
|
+
* sub-agent runs in its own worktree under `.otto-tmp/wt/<id>` — a separate
|
|
4
|
+
* working directory sharing the repo's object store, so the agents never clobber
|
|
5
|
+
* each other's files. The dir is inside the workspace, so the native OS sandbox
|
|
6
|
+
* still confines writes. `.otto-tmp/` is already gitignored.
|
|
7
|
+
*/
|
|
8
|
+
import { rmSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { git } from "./git.js";
|
|
11
|
+
/**
|
|
12
|
+
* Create an isolated worktree at HEAD under `.otto-tmp/wt/<id>`. `--detach` so
|
|
13
|
+
* the sub-agent commits onto a detached HEAD without creating or moving a branch.
|
|
14
|
+
* `cleanup()` removes the worktree (and its dir); it is idempotent and safe to
|
|
15
|
+
* call from a `finally`.
|
|
16
|
+
*/
|
|
17
|
+
export function createWorktree(workspaceDir, id) {
|
|
18
|
+
const rel = join(".otto-tmp", "wt", id);
|
|
19
|
+
const dir = join(workspaceDir, rel);
|
|
20
|
+
// Remove any stale worktree at this path first (a crashed prior run), then add.
|
|
21
|
+
git(["worktree", "remove", "--force", dir], workspaceDir);
|
|
22
|
+
rmSync(dir, { recursive: true, force: true });
|
|
23
|
+
git(["worktree", "add", "--detach", dir, "HEAD"], workspaceDir);
|
|
24
|
+
let cleaned = false;
|
|
25
|
+
const cleanup = () => {
|
|
26
|
+
if (cleaned)
|
|
27
|
+
return;
|
|
28
|
+
cleaned = true;
|
|
29
|
+
git(["worktree", "remove", "--force", dir], workspaceDir);
|
|
30
|
+
rmSync(dir, { recursive: true, force: true });
|
|
31
|
+
};
|
|
32
|
+
return { dir, cleanup };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Prune leftover worktrees from a crashed prior run: remove the `.otto-tmp/wt`
|
|
36
|
+
* tree wholesale, then GC git's worktree registry so the stale entries don't
|
|
37
|
+
* linger. Call once before a fan-out round.
|
|
38
|
+
*/
|
|
39
|
+
export function reapWorktrees(workspaceDir) {
|
|
40
|
+
rmSync(join(workspaceDir, ".otto-tmp", "wt"), { recursive: true, force: true });
|
|
41
|
+
git(["worktree", "prune"], workspaceDir);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../src/worktree.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,YAAoB,EACpB,EAAU;IAEV,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IACpC,gFAAgF;IAChF,GAAG,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;IAC1D,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;IAChE,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,GAAG,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;QAC1D,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC;IACF,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,YAAoB;IAChD,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,GAAG,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
You are a strict pre-publication secrecy reviewer. A note is about to be posted
|
|
2
|
+
publicly by an autonomous coding agent. Your ONLY job is to prevent leaks.
|
|
3
|
+
|
|
4
|
+
Decide whether the note below is SAFE to post. Treat it as UNSAFE if a reader
|
|
5
|
+
could identify the specific repository, product, company, person, or customer —
|
|
6
|
+
or if it contains code, secrets, paths, URLs, names, or any private/internal
|
|
7
|
+
detail. If there is ANY doubt whatsoever, answer UNSAFE.
|
|
8
|
+
|
|
9
|
+
Respond with EXACTLY one line and nothing else:
|
|
10
|
+
|
|
11
|
+
<journal-verdict>SAFE</journal-verdict>
|
|
12
|
+
|
|
13
|
+
or
|
|
14
|
+
|
|
15
|
+
<journal-verdict>UNSAFE</journal-verdict>
|
|
16
|
+
|
|
17
|
+
<note>
|
|
18
|
+
{{ INPUTS }}
|
|
19
|
+
</note>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
You are _a coding agent's field notes_ — you share short, generic lessons about
|
|
2
|
+
the craft of software work, never about any specific project.
|
|
3
|
+
|
|
4
|
+
Below is one durable learning. Rewrite it as a SINGLE first-person field note
|
|
5
|
+
(2–4 sentences, under 400 characters) capturing the GENERAL craft lesson.
|
|
6
|
+
|
|
7
|
+
STRICT RULES:
|
|
8
|
+
|
|
9
|
+
- No project, product, company, person, file, path, tool, version, or ticket names.
|
|
10
|
+
- No code, commands, URLs, or identifiers of any kind.
|
|
11
|
+
- If the learning cannot be generalized without specifics, output exactly: SKIP
|
|
12
|
+
- Output ONLY the note text (or SKIP). No preamble, no quotes, no markdown.
|
|
13
|
+
|
|
14
|
+
<learning>
|
|
15
|
+
{{ INPUTS }}
|
|
16
|
+
</learning>
|
package/templates/plan.md
CHANGED
|
@@ -87,9 +87,31 @@ Use the `Write` tool. An ordered checklist of **bite-sized, testable tasks**, on
|
|
|
87
87
|
Keep tasks ordered so each is gated on the prior; name the test file that pins
|
|
88
88
|
each task.
|
|
89
89
|
|
|
90
|
+
## 4b. WRITE THE TASK GRAPH (optional) — `.otto/tasks/<task-key>/tasks.json`
|
|
91
|
+
|
|
92
|
+
Use the `Write` tool to also emit a machine-readable task graph so Otto can fan
|
|
93
|
+
independent tasks out to isolated sub-agents (issue #66 P11). Shape:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"version": 1,
|
|
98
|
+
"tasks": [
|
|
99
|
+
{ "id": "t1", "title": "<short>", "fileScope": ["path/you/expect/to/touch"], "dependsOn": [], "parallelSafe": true },
|
|
100
|
+
{ "id": "t2", "title": "<short>", "fileScope": ["other/path"], "dependsOn": ["t1"], "parallelSafe": false }
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Rules: `id` unique; `dependsOn` lists earlier task ids that must land first;
|
|
106
|
+
`fileScope` lists the files the task is expected to edit; set `parallelSafe`
|
|
107
|
+
**true only when** the task shares no files and no ordering with its siblings —
|
|
108
|
+
**be conservative and default to `false` when unsure**. This file is OPTIONAL:
|
|
109
|
+
if the work does not decompose into cleanly independent tasks, omit it and the
|
|
110
|
+
run proceeds sequentially. A malformed file is ignored (fan-out simply disabled).
|
|
111
|
+
|
|
90
112
|
## 5. COMMIT
|
|
91
113
|
|
|
92
|
-
Commit ONLY the spec + plan (
|
|
93
|
-
`docs(plan):` or `chore(plan):` commit. Then print a one-line
|
|
94
|
-
task-key and the number of plan tasks authored. Do not implement;
|
|
95
|
-
reviews the plan next.
|
|
114
|
+
Commit ONLY the spec + plan + (if written) the task graph — this is the whole
|
|
115
|
+
run, no code. Use a `docs(plan):` or `chore(plan):` commit. Then print a one-line
|
|
116
|
+
summary of the task-key and the number of plan tasks authored. Do not implement;
|
|
117
|
+
the human reviews the plan next.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{{ RESUME }}
|
|
2
|
+
|
|
3
|
+
<learnings>
|
|
4
|
+
|
|
5
|
+
!?`cat ./.otto/LEARNINGS.md|||_No learnings recorded yet._`
|
|
6
|
+
|
|
7
|
+
</learnings>
|
|
8
|
+
|
|
9
|
+
<task>
|
|
10
|
+
|
|
11
|
+
You are implementing **one** task in an isolated worktree, as part of a parallel
|
|
12
|
+
fan-out (issue #66 P11). Do the whole task and nothing else.
|
|
13
|
+
|
|
14
|
+
**Task:** {{ TASK_TITLE }}
|
|
15
|
+
|
|
16
|
+
**Files you are expected to touch (your scope — do not edit files outside it):**
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
{{ TASK_SCOPE }}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Stay strictly within that file scope: a sibling sub-agent owns every other file
|
|
23
|
+
in parallel, so editing outside your scope will collide at merge time. If the
|
|
24
|
+
task genuinely cannot be done without touching a file outside the scope, do as
|
|
25
|
+
much as you safely can within scope and note the gap in your commit message.
|
|
26
|
+
|
|
27
|
+
Write the failing test first where it applies, implement, run the relevant
|
|
28
|
+
feedback loop, and make a single focused commit for this task. Do not push.
|
|
29
|
+
|
|
30
|
+
</task>
|
|
31
|
+
|
|
32
|
+
@include:prompt.md
|