personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Relicense project to AGPL-3.0-only

- Add official AGPL-3.0 LICENSE from gnu.org
- Add CONTRIBUTING.md with DCO sign-off requirement
- Update pyproject.toml license field and classifier
- Update README with sol pbc attribution and AGPL license section
- Update docs/VENDOR.md to reference AGPL-compatible licenses
- Add SPDX-License-Identifier headers to all 188 source files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+1386 -93
+21
CONTRIBUTING.md
··· 1 + # Contributing to solstone 2 + 3 + Thank you for your interest in contributing to solstone. 4 + 5 + ## License of Contributions 6 + 7 + By contributing to this repository, you agree that your contributions are 8 + licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-only), 9 + the same license as the project. 10 + 11 + You represent that you have the right to submit the contribution and that it 12 + does not include proprietary, confidential, or third-party code that is 13 + incompatible with the AGPL. 14 + 15 + ## Developer Certificate of Origin (DCO) 16 + 17 + All contributions must be signed off using: 18 + 19 + git commit -s 20 + 21 + This certifies compliance with the Developer Certificate of Origin (DCO).
+661
LICENSE
··· 1 + GNU AFFERO GENERAL PUBLIC LICENSE 2 + Version 3, 19 November 2007 3 + 4 + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> 5 + Everyone is permitted to copy and distribute verbatim copies 6 + of this license document, but changing it is not allowed. 7 + 8 + Preamble 9 + 10 + The GNU Affero General Public License is a free, copyleft license for 11 + software and other kinds of works, specifically designed to ensure 12 + cooperation with the community in the case of network server software. 13 + 14 + The licenses for most software and other practical works are designed 15 + to take away your freedom to share and change the works. By contrast, 16 + our General Public Licenses are intended to guarantee your freedom to 17 + share and change all versions of a program--to make sure it remains free 18 + software for all its users. 19 + 20 + When we speak of free software, we are referring to freedom, not 21 + price. Our General Public Licenses are designed to make sure that you 22 + have the freedom to distribute copies of free software (and charge for 23 + them if you wish), that you receive source code or can get it if you 24 + want it, that you can change the software or use pieces of it in new 25 + free programs, and that you know you can do these things. 26 + 27 + Developers that use our General Public Licenses protect your rights 28 + with two steps: (1) assert copyright on the software, and (2) offer 29 + you this License which gives you legal permission to copy, distribute 30 + and/or modify the software. 31 + 32 + A secondary benefit of defending all users' freedom is that 33 + improvements made in alternate versions of the program, if they 34 + receive widespread use, become available for other developers to 35 + incorporate. Many developers of free software are heartened and 36 + encouraged by the resulting cooperation. However, in the case of 37 + software used on network servers, this result may fail to come about. 38 + The GNU General Public License permits making a modified version and 39 + letting the public access it on a server without ever releasing its 40 + source code to the public. 41 + 42 + The GNU Affero General Public License is designed specifically to 43 + ensure that, in such cases, the modified source code becomes available 44 + to the community. It requires the operator of a network server to 45 + provide the source code of the modified version running there to the 46 + users of that server. Therefore, public use of a modified version, on 47 + a publicly accessible server, gives the public access to the source 48 + code of the modified version. 49 + 50 + An older license, called the Affero General Public License and 51 + published by Affero, was designed to accomplish similar goals. This is 52 + a different license, not a version of the Affero GPL, but Affero has 53 + released a new version of the Affero GPL which permits relicensing under 54 + this license. 55 + 56 + The precise terms and conditions for copying, distribution and 57 + modification follow. 58 + 59 + TERMS AND CONDITIONS 60 + 61 + 0. Definitions. 62 + 63 + "This License" refers to version 3 of the GNU Affero General Public License. 64 + 65 + "Copyright" also means copyright-like laws that apply to other kinds of 66 + works, such as semiconductor masks. 67 + 68 + "The Program" refers to any copyrightable work licensed under this 69 + License. Each licensee is addressed as "you". "Licensees" and 70 + "recipients" may be individuals or organizations. 71 + 72 + To "modify" a work means to copy from or adapt all or part of the work 73 + in a fashion requiring copyright permission, other than the making of an 74 + exact copy. The resulting work is called a "modified version" of the 75 + earlier work or a work "based on" the earlier work. 76 + 77 + A "covered work" means either the unmodified Program or a work based 78 + on the Program. 79 + 80 + To "propagate" a work means to do anything with it that, without 81 + permission, would make you directly or secondarily liable for 82 + infringement under applicable copyright law, except executing it on a 83 + computer or modifying a private copy. Propagation includes copying, 84 + distribution (with or without modification), making available to the 85 + public, and in some countries other activities as well. 86 + 87 + To "convey" a work means any kind of propagation that enables other 88 + parties to make or receive copies. Mere interaction with a user through 89 + a computer network, with no transfer of a copy, is not conveying. 90 + 91 + An interactive user interface displays "Appropriate Legal Notices" 92 + to the extent that it includes a convenient and prominently visible 93 + feature that (1) displays an appropriate copyright notice, and (2) 94 + tells the user that there is no warranty for the work (except to the 95 + extent that warranties are provided), that licensees may convey the 96 + work under this License, and how to view a copy of this License. If 97 + the interface presents a list of user commands or options, such as a 98 + menu, a prominent item in the list meets this criterion. 99 + 100 + 1. Source Code. 101 + 102 + The "source code" for a work means the preferred form of the work 103 + for making modifications to it. "Object code" means any non-source 104 + form of a work. 105 + 106 + A "Standard Interface" means an interface that either is an official 107 + standard defined by a recognized standards body, or, in the case of 108 + interfaces specified for a particular programming language, one that 109 + is widely used among developers working in that language. 110 + 111 + The "System Libraries" of an executable work include anything, other 112 + than the work as a whole, that (a) is included in the normal form of 113 + packaging a Major Component, but which is not part of that Major 114 + Component, and (b) serves only to enable use of the work with that 115 + Major Component, or to implement a Standard Interface for which an 116 + implementation is available to the public in source code form. A 117 + "Major Component", in this context, means a major essential component 118 + (kernel, window system, and so on) of the specific operating system 119 + (if any) on which the executable work runs, or a compiler used to 120 + produce the work, or an object code interpreter used to run it. 121 + 122 + The "Corresponding Source" for a work in object code form means all 123 + the source code needed to generate, install, and (for an executable 124 + work) run the object code and to modify the work, including scripts to 125 + control those activities. However, it does not include the work's 126 + System Libraries, or general-purpose tools or generally available free 127 + programs which are used unmodified in performing those activities but 128 + which are not part of the work. For example, Corresponding Source 129 + includes interface definition files associated with source files for 130 + the work, and the source code for shared libraries and dynamically 131 + linked subprograms that the work is specifically designed to require, 132 + such as by intimate data communication or control flow between those 133 + subprograms and other parts of the work. 134 + 135 + The Corresponding Source need not include anything that users 136 + can regenerate automatically from other parts of the Corresponding 137 + Source. 138 + 139 + The Corresponding Source for a work in source code form is that 140 + same work. 141 + 142 + 2. Basic Permissions. 143 + 144 + All rights granted under this License are granted for the term of 145 + copyright on the Program, and are irrevocable provided the stated 146 + conditions are met. This License explicitly affirms your unlimited 147 + permission to run the unmodified Program. The output from running a 148 + covered work is covered by this License only if the output, given its 149 + content, constitutes a covered work. This License acknowledges your 150 + rights of fair use or other equivalent, as provided by copyright law. 151 + 152 + You may make, run and propagate covered works that you do not 153 + convey, without conditions so long as your license otherwise remains 154 + in force. You may convey covered works to others for the sole purpose 155 + of having them make modifications exclusively for you, or provide you 156 + with facilities for running those works, provided that you comply with 157 + the terms of this License in conveying all material for which you do 158 + not control copyright. Those thus making or running the covered works 159 + for you must do so exclusively on your behalf, under your direction 160 + and control, on terms that prohibit them from making any copies of 161 + your copyrighted material outside their relationship with you. 162 + 163 + Conveying under any other circumstances is permitted solely under 164 + the conditions stated below. Sublicensing is not allowed; section 10 165 + makes it unnecessary. 166 + 167 + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 + 169 + No covered work shall be deemed part of an effective technological 170 + measure under any applicable law fulfilling obligations under article 171 + 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 + similar laws prohibiting or restricting circumvention of such 173 + measures. 174 + 175 + When you convey a covered work, you waive any legal power to forbid 176 + circumvention of technological measures to the extent such circumvention 177 + is effected by exercising rights under this License with respect to 178 + the covered work, and you disclaim any intention to limit operation or 179 + modification of the work as a means of enforcing, against the work's 180 + users, your or third parties' legal rights to forbid circumvention of 181 + technological measures. 182 + 183 + 4. Conveying Verbatim Copies. 184 + 185 + You may convey verbatim copies of the Program's source code as you 186 + receive it, in any medium, provided that you conspicuously and 187 + appropriately publish on each copy an appropriate copyright notice; 188 + keep intact all notices stating that this License and any 189 + non-permissive terms added in accord with section 7 apply to the code; 190 + keep intact all notices of the absence of any warranty; and give all 191 + recipients a copy of this License along with the Program. 192 + 193 + You may charge any price or no price for each copy that you convey, 194 + and you may offer support or warranty protection for a fee. 195 + 196 + 5. Conveying Modified Source Versions. 197 + 198 + You may convey a work based on the Program, or the modifications to 199 + produce it from the Program, in the form of source code under the 200 + terms of section 4, provided that you also meet all of these conditions: 201 + 202 + a) The work must carry prominent notices stating that you modified 203 + it, and giving a relevant date. 204 + 205 + b) The work must carry prominent notices stating that it is 206 + released under this License and any conditions added under section 207 + 7. This requirement modifies the requirement in section 4 to 208 + "keep intact all notices". 209 + 210 + c) You must license the entire work, as a whole, under this 211 + License to anyone who comes into possession of a copy. This 212 + License will therefore apply, along with any applicable section 7 213 + additional terms, to the whole of the work, and all its parts, 214 + regardless of how they are packaged. This License gives no 215 + permission to license the work in any other way, but it does not 216 + invalidate such permission if you have separately received it. 217 + 218 + d) If the work has interactive user interfaces, each must display 219 + Appropriate Legal Notices; however, if the Program has interactive 220 + interfaces that do not display Appropriate Legal Notices, your 221 + work need not make them do so. 222 + 223 + A compilation of a covered work with other separate and independent 224 + works, which are not by their nature extensions of the covered work, 225 + and which are not combined with it such as to form a larger program, 226 + in or on a volume of a storage or distribution medium, is called an 227 + "aggregate" if the compilation and its resulting copyright are not 228 + used to limit the access or legal rights of the compilation's users 229 + beyond what the individual works permit. Inclusion of a covered work 230 + in an aggregate does not cause this License to apply to the other 231 + parts of the aggregate. 232 + 233 + 6. Conveying Non-Source Forms. 234 + 235 + You may convey a covered work in object code form under the terms 236 + of sections 4 and 5, provided that you also convey the 237 + machine-readable Corresponding Source under the terms of this License, 238 + in one of these ways: 239 + 240 + a) Convey the object code in, or embodied in, a physical product 241 + (including a physical distribution medium), accompanied by the 242 + Corresponding Source fixed on a durable physical medium 243 + customarily used for software interchange. 244 + 245 + b) Convey the object code in, or embodied in, a physical product 246 + (including a physical distribution medium), accompanied by a 247 + written offer, valid for at least three years and valid for as 248 + long as you offer spare parts or customer support for that product 249 + model, to give anyone who possesses the object code either (1) a 250 + copy of the Corresponding Source for all the software in the 251 + product that is covered by this License, on a durable physical 252 + medium customarily used for software interchange, for a price no 253 + more than your reasonable cost of physically performing this 254 + conveying of source, or (2) access to copy the 255 + Corresponding Source from a network server at no charge. 256 + 257 + c) Convey individual copies of the object code with a copy of the 258 + written offer to provide the Corresponding Source. This 259 + alternative is allowed only occasionally and noncommercially, and 260 + only if you received the object code with such an offer, in accord 261 + with subsection 6b. 262 + 263 + d) Convey the object code by offering access from a designated 264 + place (gratis or for a charge), and offer equivalent access to the 265 + Corresponding Source in the same way through the same place at no 266 + further charge. You need not require recipients to copy the 267 + Corresponding Source along with the object code. If the place to 268 + copy the object code is a network server, the Corresponding Source 269 + may be on a different server (operated by you or a third party) 270 + that supports equivalent copying facilities, provided you maintain 271 + clear directions next to the object code saying where to find the 272 + Corresponding Source. Regardless of what server hosts the 273 + Corresponding Source, you remain obligated to ensure that it is 274 + available for as long as needed to satisfy these requirements. 275 + 276 + e) Convey the object code using peer-to-peer transmission, provided 277 + you inform other peers where the object code and Corresponding 278 + Source of the work are being offered to the general public at no 279 + charge under subsection 6d. 280 + 281 + A separable portion of the object code, whose source code is excluded 282 + from the Corresponding Source as a System Library, need not be 283 + included in conveying the object code work. 284 + 285 + A "User Product" is either (1) a "consumer product", which means any 286 + tangible personal property which is normally used for personal, family, 287 + or household purposes, or (2) anything designed or sold for incorporation 288 + into a dwelling. In determining whether a product is a consumer product, 289 + doubtful cases shall be resolved in favor of coverage. For a particular 290 + product received by a particular user, "normally used" refers to a 291 + typical or common use of that class of product, regardless of the status 292 + of the particular user or of the way in which the particular user 293 + actually uses, or expects or is expected to use, the product. A product 294 + is a consumer product regardless of whether the product has substantial 295 + commercial, industrial or non-consumer uses, unless such uses represent 296 + the only significant mode of use of the product. 297 + 298 + "Installation Information" for a User Product means any methods, 299 + procedures, authorization keys, or other information required to install 300 + and execute modified versions of a covered work in that User Product from 301 + a modified version of its Corresponding Source. The information must 302 + suffice to ensure that the continued functioning of the modified object 303 + code is in no case prevented or interfered with solely because 304 + modification has been made. 305 + 306 + If you convey an object code work under this section in, or with, or 307 + specifically for use in, a User Product, and the conveying occurs as 308 + part of a transaction in which the right of possession and use of the 309 + User Product is transferred to the recipient in perpetuity or for a 310 + fixed term (regardless of how the transaction is characterized), the 311 + Corresponding Source conveyed under this section must be accompanied 312 + by the Installation Information. But this requirement does not apply 313 + if neither you nor any third party retains the ability to install 314 + modified object code on the User Product (for example, the work has 315 + been installed in ROM). 316 + 317 + The requirement to provide Installation Information does not include a 318 + requirement to continue to provide support service, warranty, or updates 319 + for a work that has been modified or installed by the recipient, or for 320 + the User Product in which it has been modified or installed. Access to a 321 + network may be denied when the modification itself materially and 322 + adversely affects the operation of the network or violates the rules and 323 + protocols for communication across the network. 324 + 325 + Corresponding Source conveyed, and Installation Information provided, 326 + in accord with this section must be in a format that is publicly 327 + documented (and with an implementation available to the public in 328 + source code form), and must require no special password or key for 329 + unpacking, reading or copying. 330 + 331 + 7. Additional Terms. 332 + 333 + "Additional permissions" are terms that supplement the terms of this 334 + License by making exceptions from one or more of its conditions. 335 + Additional permissions that are applicable to the entire Program shall 336 + be treated as though they were included in this License, to the extent 337 + that they are valid under applicable law. If additional permissions 338 + apply only to part of the Program, that part may be used separately 339 + under those permissions, but the entire Program remains governed by 340 + this License without regard to the additional permissions. 341 + 342 + When you convey a copy of a covered work, you may at your option 343 + remove any additional permissions from that copy, or from any part of 344 + it. (Additional permissions may be written to require their own 345 + removal in certain cases when you modify the work.) You may place 346 + additional permissions on material, added by you to a covered work, 347 + for which you have or can give appropriate copyright permission. 348 + 349 + Notwithstanding any other provision of this License, for material you 350 + add to a covered work, you may (if authorized by the copyright holders of 351 + that material) supplement the terms of this License with terms: 352 + 353 + a) Disclaiming warranty or limiting liability differently from the 354 + terms of sections 15 and 16 of this License; or 355 + 356 + b) Requiring preservation of specified reasonable legal notices or 357 + author attributions in that material or in the Appropriate Legal 358 + Notices displayed by works containing it; or 359 + 360 + c) Prohibiting misrepresentation of the origin of that material, or 361 + requiring that modified versions of such material be marked in 362 + reasonable ways as different from the original version; or 363 + 364 + d) Limiting the use for publicity purposes of names of licensors or 365 + authors of the material; or 366 + 367 + e) Declining to grant rights under trademark law for use of some 368 + trade names, trademarks, or service marks; or 369 + 370 + f) Requiring indemnification of licensors and authors of that 371 + material by anyone who conveys the material (or modified versions of 372 + it) with contractual assumptions of liability to the recipient, for 373 + any liability that these contractual assumptions directly impose on 374 + those licensors and authors. 375 + 376 + All other non-permissive additional terms are considered "further 377 + restrictions" within the meaning of section 10. If the Program as you 378 + received it, or any part of it, contains a notice stating that it is 379 + governed by this License along with a term that is a further 380 + restriction, you may remove that term. If a license document contains 381 + a further restriction but permits relicensing or conveying under this 382 + License, you may add to a covered work material governed by the terms 383 + of that license document, provided that the further restriction does 384 + not survive such relicensing or conveying. 385 + 386 + If you add terms to a covered work in accord with this section, you 387 + must place, in the relevant source files, a statement of the 388 + additional terms that apply to those files, or a notice indicating 389 + where to find the applicable terms. 390 + 391 + Additional terms, permissive or non-permissive, may be stated in the 392 + form of a separately written license, or stated as exceptions; 393 + the above requirements apply either way. 394 + 395 + 8. Termination. 396 + 397 + You may not propagate or modify a covered work except as expressly 398 + provided under this License. Any attempt otherwise to propagate or 399 + modify it is void, and will automatically terminate your rights under 400 + this License (including any patent licenses granted under the third 401 + paragraph of section 11). 402 + 403 + However, if you cease all violation of this License, then your 404 + license from a particular copyright holder is reinstated (a) 405 + provisionally, unless and until the copyright holder explicitly and 406 + finally terminates your license, and (b) permanently, if the copyright 407 + holder fails to notify you of the violation by some reasonable means 408 + prior to 60 days after the cessation. 409 + 410 + Moreover, your license from a particular copyright holder is 411 + reinstated permanently if the copyright holder notifies you of the 412 + violation by some reasonable means, this is the first time you have 413 + received notice of violation of this License (for any work) from that 414 + copyright holder, and you cure the violation prior to 30 days after 415 + your receipt of the notice. 416 + 417 + Termination of your rights under this section does not terminate the 418 + licenses of parties who have received copies or rights from you under 419 + this License. If your rights have been terminated and not permanently 420 + reinstated, you do not qualify to receive new licenses for the same 421 + material under section 10. 422 + 423 + 9. Acceptance Not Required for Having Copies. 424 + 425 + You are not required to accept this License in order to receive or 426 + run a copy of the Program. Ancillary propagation of a covered work 427 + occurring solely as a consequence of using peer-to-peer transmission 428 + to receive a copy likewise does not require acceptance. However, 429 + nothing other than this License grants you permission to propagate or 430 + modify any covered work. These actions infringe copyright if you do 431 + not accept this License. Therefore, by modifying or propagating a 432 + covered work, you indicate your acceptance of this License to do so. 433 + 434 + 10. Automatic Licensing of Downstream Recipients. 435 + 436 + Each time you convey a covered work, the recipient automatically 437 + receives a license from the original licensors, to run, modify and 438 + propagate that work, subject to this License. You are not responsible 439 + for enforcing compliance by third parties with this License. 440 + 441 + An "entity transaction" is a transaction transferring control of an 442 + organization, or substantially all assets of one, or subdividing an 443 + organization, or merging organizations. If propagation of a covered 444 + work results from an entity transaction, each party to that 445 + transaction who receives a copy of the work also receives whatever 446 + licenses to the work the party's predecessor in interest had or could 447 + give under the previous paragraph, plus a right to possession of the 448 + Corresponding Source of the work from the predecessor in interest, if 449 + the predecessor has it or can get it with reasonable efforts. 450 + 451 + You may not impose any further restrictions on the exercise of the 452 + rights granted or affirmed under this License. For example, you may 453 + not impose a license fee, royalty, or other charge for exercise of 454 + rights granted under this License, and you may not initiate litigation 455 + (including a cross-claim or counterclaim in a lawsuit) alleging that 456 + any patent claim is infringed by making, using, selling, offering for 457 + sale, or importing the Program or any portion of it. 458 + 459 + 11. Patents. 460 + 461 + A "contributor" is a copyright holder who authorizes use under this 462 + License of the Program or a work on which the Program is based. The 463 + work thus licensed is called the contributor's "contributor version". 464 + 465 + A contributor's "essential patent claims" are all patent claims 466 + owned or controlled by the contributor, whether already acquired or 467 + hereafter acquired, that would be infringed by some manner, permitted 468 + by this License, of making, using, or selling its contributor version, 469 + but do not include claims that would be infringed only as a 470 + consequence of further modification of the contributor version. For 471 + purposes of this definition, "control" includes the right to grant 472 + patent sublicenses in a manner consistent with the requirements of 473 + this License. 474 + 475 + Each contributor grants you a non-exclusive, worldwide, royalty-free 476 + patent license under the contributor's essential patent claims, to 477 + make, use, sell, offer for sale, import and otherwise run, modify and 478 + propagate the contents of its contributor version. 479 + 480 + In the following three paragraphs, a "patent license" is any express 481 + agreement or commitment, however denominated, not to enforce a patent 482 + (such as an express permission to practice a patent or covenant not to 483 + sue for patent infringement). To "grant" such a patent license to a 484 + party means to make such an agreement or commitment not to enforce a 485 + patent against the party. 486 + 487 + If you convey a covered work, knowingly relying on a patent license, 488 + and the Corresponding Source of the work is not available for anyone 489 + to copy, free of charge and under the terms of this License, through a 490 + publicly available network server or other readily accessible means, 491 + then you must either (1) cause the Corresponding Source to be so 492 + available, or (2) arrange to deprive yourself of the benefit of the 493 + patent license for this particular work, or (3) arrange, in a manner 494 + consistent with the requirements of this License, to extend the patent 495 + license to downstream recipients. "Knowingly relying" means you have 496 + actual knowledge that, but for the patent license, your conveying the 497 + covered work in a country, or your recipient's use of the covered work 498 + in a country, would infringe one or more identifiable patents in that 499 + country that you have reason to believe are valid. 500 + 501 + If, pursuant to or in connection with a single transaction or 502 + arrangement, you convey, or propagate by procuring conveyance of, a 503 + covered work, and grant a patent license to some of the parties 504 + receiving the covered work authorizing them to use, propagate, modify 505 + or convey a specific copy of the covered work, then the patent license 506 + you grant is automatically extended to all recipients of the covered 507 + work and works based on it. 508 + 509 + A patent license is "discriminatory" if it does not include within 510 + the scope of its coverage, prohibits the exercise of, or is 511 + conditioned on the non-exercise of one or more of the rights that are 512 + specifically granted under this License. You may not convey a covered 513 + work if you are a party to an arrangement with a third party that is 514 + in the business of distributing software, under which you make payment 515 + to the third party based on the extent of your activity of conveying 516 + the work, and under which the third party grants, to any of the 517 + parties who would receive the covered work from you, a discriminatory 518 + patent license (a) in connection with copies of the covered work 519 + conveyed by you (or copies made from those copies), or (b) primarily 520 + for and in connection with specific products or compilations that 521 + contain the covered work, unless you entered into that arrangement, 522 + or that patent license was granted, prior to 28 March 2007. 523 + 524 + Nothing in this License shall be construed as excluding or limiting 525 + any implied license or other defenses to infringement that may 526 + otherwise be available to you under applicable patent law. 527 + 528 + 12. No Surrender of Others' Freedom. 529 + 530 + If conditions are imposed on you (whether by court order, agreement or 531 + otherwise) that contradict the conditions of this License, they do not 532 + excuse you from the conditions of this License. If you cannot convey a 533 + covered work so as to satisfy simultaneously your obligations under this 534 + License and any other pertinent obligations, then as a consequence you may 535 + not convey it at all. For example, if you agree to terms that obligate you 536 + to collect a royalty for further conveying from those to whom you convey 537 + the Program, the only way you could satisfy both those terms and this 538 + License would be to refrain entirely from conveying the Program. 539 + 540 + 13. Remote Network Interaction; Use with the GNU General Public License. 541 + 542 + Notwithstanding any other provision of this License, if you modify the 543 + Program, your modified version must prominently offer all users 544 + interacting with it remotely through a computer network (if your version 545 + supports such interaction) an opportunity to receive the Corresponding 546 + Source of your version by providing access to the Corresponding Source 547 + from a network server at no charge, through some standard or customary 548 + means of facilitating copying of software. This Corresponding Source 549 + shall include the Corresponding Source for any work covered by version 3 550 + of the GNU General Public License that is incorporated pursuant to the 551 + following paragraph. 552 + 553 + Notwithstanding any other provision of this License, you have 554 + permission to link or combine any covered work with a work licensed 555 + under version 3 of the GNU General Public License into a single 556 + combined work, and to convey the resulting work. The terms of this 557 + License will continue to apply to the part which is the covered work, 558 + but the work with which it is combined will remain governed by version 559 + 3 of the GNU General Public License. 560 + 561 + 14. Revised Versions of this License. 562 + 563 + The Free Software Foundation may publish revised and/or new versions of 564 + the GNU Affero General Public License from time to time. Such new versions 565 + will be similar in spirit to the present version, but may differ in detail to 566 + address new problems or concerns. 567 + 568 + Each version is given a distinguishing version number. If the 569 + Program specifies that a certain numbered version of the GNU Affero General 570 + Public License "or any later version" applies to it, you have the 571 + option of following the terms and conditions either of that numbered 572 + version or of any later version published by the Free Software 573 + Foundation. If the Program does not specify a version number of the 574 + GNU Affero General Public License, you may choose any version ever published 575 + by the Free Software Foundation. 576 + 577 + If the Program specifies that a proxy can decide which future 578 + versions of the GNU Affero General Public License can be used, that proxy's 579 + public statement of acceptance of a version permanently authorizes you 580 + to choose that version for the Program. 581 + 582 + Later license versions may give you additional or different 583 + permissions. However, no additional obligations are imposed on any 584 + author or copyright holder as a result of your choosing to follow a 585 + later version. 586 + 587 + 15. Disclaimer of Warranty. 588 + 589 + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 + HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 + OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 + IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 + ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 + 598 + 16. Limitation of Liability. 599 + 600 + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 + THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 + GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 + USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 + EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 + SUCH DAMAGES. 609 + 610 + 17. Interpretation of Sections 15 and 16. 611 + 612 + If the disclaimer of warranty and limitation of liability provided 613 + above cannot be given local legal effect according to their terms, 614 + reviewing courts shall apply local law that most closely approximates 615 + an absolute waiver of all civil liability in connection with the 616 + Program, unless a warranty or assumption of liability accompanies a 617 + copy of the Program in return for a fee. 618 + 619 + END OF TERMS AND CONDITIONS 620 + 621 + How to Apply These Terms to Your New Programs 622 + 623 + If you develop a new program, and you want it to be of the greatest 624 + possible use to the public, the best way to achieve this is to make it 625 + free software which everyone can redistribute and change under these terms. 626 + 627 + To do so, attach the following notices to the program. It is safest 628 + to attach them to the start of each source file to most effectively 629 + state the exclusion of warranty; and each file should have at least 630 + the "copyright" line and a pointer to where the full notice is found. 631 + 632 + <one line to give the program's name and a brief idea of what it does.> 633 + Copyright (C) <year> <name of author> 634 + 635 + This program is free software: you can redistribute it and/or modify 636 + it under the terms of the GNU Affero General Public License as published by 637 + the Free Software Foundation, either version 3 of the License, or 638 + (at your option) any later version. 639 + 640 + This program is distributed in the hope that it will be useful, 641 + but WITHOUT ANY WARRANTY; without even the implied warranty of 642 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 + GNU Affero General Public License for more details. 644 + 645 + You should have received a copy of the GNU Affero General Public License 646 + along with this program. If not, see <https://www.gnu.org/licenses/>. 647 + 648 + Also add information on how to contact you by electronic and paper mail. 649 + 650 + If your software can interact with users remotely through a computer 651 + network, you should also make sure that it provides a way for users to 652 + get its source. For example, if your program is a web application, its 653 + interface could display a "Source" link that leads users to an archive 654 + of the code. There are many ways you could offer source, and different 655 + solutions will be better for different programs; see section 13 for the 656 + specific requirements. 657 + 658 + You should also get your employer (if you work as a programmer) or school, 659 + if any, to sign a "copyright disclaimer" for the program, if necessary. 660 + For more information on this, and how to apply and follow the GNU AGPL, see 661 + <https://www.gnu.org/licenses/>.
+13 -3
README.md
··· 1 1 <img src="logo.png" alt="solstone Logo" width="300"> 2 2 3 3 # solstone 4 + 5 + solstone is an open source project maintained by sol pbc. 6 + 4 7 Navigate Work Intelligently 5 8 6 9 A comprehensive Python-based AI-driven desktop journaling toolkit for multimodal capture, analysis, and intelligent navigation of workplace activities. solstone organizes captured data under a **journal** directory containing daily `YYYYMMDD` folders, enabling powerful temporal analysis and review. ··· 154 157 155 158 ## 🤝 Contributing 156 159 157 - Please read [AGENTS.md](AGENTS.md) for development guidelines, coding standards, and contribution instructions. 160 + Please read [CONTRIBUTING.md](CONTRIBUTING.md) for contribution terms and [AGENTS.md](AGENTS.md) for development guidelines. 161 + 162 + ## License 163 + 164 + This project is licensed under the GNU Affero General Public License v3.0 165 + (AGPL-3.0-only). 158 166 159 - ## 📄 License 167 + If you modify this software and allow users to interact with it over a network, 168 + you must make the complete corresponding source code of your modified version 169 + available to those users under the same license. 160 170 161 - MIT License - see LICENSE file for details 171 + See the LICENSE file for details.
+3
apps/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """App plugin system for solstone. 2 5 3 6 Convention-based app discovery with minimal configuration:
+3
apps/agents/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import asyncio
+3
apps/calendar/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import json
+3
apps/chat/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import logging
+3
apps/chat/tools.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP tools for the chat app.""" 2 5 3 6 import json
+3
apps/entities/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Entities app routes - facet entity management.""" 2 5 3 6 from __future__ import annotations
+3
apps/entities/tools.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP tools for entity management. 2 5 3 6 This module provides the entity MCP tools for the entities app.
+3
apps/home/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Home app - daily dashboard with facet-aware summary.""" 2 5 3 6 from __future__ import annotations
+3
apps/import/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import time
+3
apps/insights/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Insights app - browse daily insight markdown files.""" 2 5 3 6 from __future__ import annotations
+3
apps/search/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import re
+3
apps/settings/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import json
+3
apps/speakers/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Speaker voiceprint management app.""" 2 5 3 6 from __future__ import annotations
+2
apps/speakers/tests/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc
+3
apps/speakers/tests/conftest.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Self-contained fixtures for speakers app tests. 2 5 3 6 These fixtures are fully standalone and only depend on pytest builtins.
+3
apps/speakers/tests/test_routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for speakers app.""" 2 5 3 6 import numpy as np
+3
apps/stats/dashboard.js
··· 1 + // SPDX-License-Identifier: AGPL-3.0-only 2 + // Copyright (c) 2026 sol pbc 3 + 1 4 // Dashboard module for client-side rendering 2 5 const Dashboard = (function() { 3 6 'use strict';
+3
apps/stats/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import json
+3
apps/todos/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 from datetime import date, datetime, timedelta
+3
apps/todos/tests/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for the todos app."""
+3
apps/todos/tests/conftest.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Self-contained fixtures for todos app tests. 2 5 3 6 These fixtures are fully standalone and only depend on pytest builtins.
+3
apps/todos/tests/test_logging.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Test audit logging for todos app MCP tool actions.""" 2 5 3 6 import json
+3
apps/todos/tests/test_todo.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for the facet-scoped todo checklist system.""" 2 5 3 6 from __future__ import annotations
+3
apps/todos/tests/test_tools.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for todos app MCP tool helpers and handlers.""" 2 5 3 6 from __future__ import annotations
+3
apps/todos/todo.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Todo checklist utilities shared across think components. 2 5 3 6 Todos are stored as JSONL files with one JSON object per line. Line number (1-indexed)
+3
apps/todos/tools.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP tools and resources for todo management. 2 5 3 6 This module provides the todo MCP tools and resource handler for the todos app.
+3
apps/tokens/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Token usage and cost tracking app.""" 2 5 3 6 from __future__ import annotations
+3
apps/transcripts/routes.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Transcript viewer app - browse and playback daily transcripts.""" 2 5 3 6 from __future__ import annotations
+3
apps/utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Utility functions for Convey app storage in journal.""" 2 5 3 6 import re
+3
convey/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Web interface for navigating and interacting with journal data.""" 2 5 3 6 from __future__ import annotations
+3
convey/apps.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """App plugin system context processors and helpers.""" 2 5 3 6 from __future__ import annotations
+3
convey/bridge.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Bridge between Callosum message bus and WebSocket clients. 2 5 3 6 Listens to all Callosum events (cortex, task, indexer, etc.) and broadcasts them
+3
convey/cli.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """CLI entry points for Convey web interface.""" 2 5 3 6 from __future__ import annotations
+3
convey/config.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Convey configuration management and API routes.""" 2 5 3 6 from __future__ import annotations
+3
convey/gentag.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """ 3 6 Generate ArUco marker PNG for corner tag detection. 4 7
+3
convey/restart.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """Restart utility for Convey web service.""" 3 6 4 7 from __future__ import annotations
+3
convey/root.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Root blueprint: authentication and core routes.""" 2 5 3 6 from __future__ import annotations
+3
convey/screenshot.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """Screenshot utility for Convey web views.""" 3 6 4 7 from __future__ import annotations
+3
convey/state.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 journal_root: str = ""
+3
convey/static/app.js
··· 1 + // SPDX-License-Identifier: AGPL-3.0-only 2 + // Copyright (c) 2026 sol pbc 3 + 1 4 /** 2 5 * App System JavaScript 3 6 * Handles facet selection, menu interactions, and responsive UI for app.html
+3
convey/static/colors.js
··· 1 + // SPDX-License-Identifier: AGPL-3.0-only 2 + // Copyright (c) 2026 sol pbc 3 + 1 4 window.CATEGORY_COLORS = ['#007bff','#28a745','#17a2b8','#ffc107','#6f42c1','#fd7e14','#e83e8c','#6c757d','#20c997','#ff5722','#9c27b0','#795548'];
+3
convey/static/error-handler.js
··· 1 + // SPDX-License-Identifier: AGPL-3.0-only 2 + // Copyright (c) 2026 sol pbc 3 + 1 4 /** 2 5 * Error Handler for App System 3 6 * Captures JavaScript errors and provides visual feedback
+3
convey/static/month-picker.js
··· 1 + // SPDX-License-Identifier: AGPL-3.0-only 2 + // Copyright (c) 2026 sol pbc 3 + 1 4 /** 2 5 * Month Picker Widget 3 6 * Dropdown calendar for date navigation with per-app heat map support.
+3
convey/static/websocket.js
··· 1 + // SPDX-License-Identifier: AGPL-3.0-only 2 + // Copyright (c) 2026 sol pbc 3 + 1 4 /** 2 5 * Callosum WebSocket Bridge 3 6 *
+3
convey/utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import json 2 5 import re 3 6 import time
+1 -1
docs/VENDOR.md
··· 56 56 57 57 1. **Create subdirectory**: `vendor/{library_name}/` 58 58 2. **Add minified file**: Copy production-ready `.min.js` file 59 - 3. **Check license**: Ensure license is MIT-compatible and included 59 + 3. **Check license**: Ensure license is AGPL-compatible and included 60 60 4. **Update this manifest**: Add entry with version, purpose, and usage 61 61 5. **Test**: Verify library loads and works in development 62 62
+3
muse/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Muse - AI Agent orchestration and execution system for solstone."""
+3
muse/agents.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import argparse
+3
muse/anthropic.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """Anthropic Claude backed agent implementation. 3 6 4 7 This module provides the Anthropic Claude backend for the ``muse-agents`` CLI.
+3
muse/claude.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """Claude Code SDK backend agent implementation. 3 6 4 7 This module exposes agent functionality for interacting with Claude Code
+3
muse/cli.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """Muse CLI - Run AI agents directly or through Cortex. 3 6 4 7 Usage:
+3
muse/cortex.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Callosum-based agent process manager for solstone. 2 5 3 6 Cortex listens for agent requests via the Callosum message bus and manages
+3
muse/cortex_client.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Cortex client for managing AI agent requests.""" 2 5 3 6 import json
+3
muse/google.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """Gemini backed agent implementation. 3 6 4 7 This module provides the Google Gemini backend for the ``muse-agents`` CLI.
+3
muse/mcp.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """MCP server for solstone journal assistant. 3 6 4 7 This module creates the FastMCP server instance and registers all tools and resources
+3
muse/openai.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """ 3 6 OpenAI-backed agent implementation for the solstone `muse-agents` CLI. 4 7
+2
muse/resources/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc
+3
muse/resources/insights.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP resource handlers for insights.""" 2 5 3 6 import os
+3
muse/resources/media.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP resource handlers for media.""" 2 5 3 6 import os
+3
muse/resources/transcripts.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP resource handlers for transcripts.""" 2 5 3 6 from datetime import datetime, timedelta
+2
muse/tools/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc
+3
muse/tools/facets.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP tools for facet management. 2 5 3 6 Note: These functions are registered as MCP tools by muse/mcp.py
+3
muse/tools/messaging.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP tools for resource operations. 2 5 3 6 Note: These functions are registered as MCP tools by muse/mcp.py
+3
muse/tools/search.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """MCP tools for search operations. 2 5 3 6 Note: These functions are registered as MCP tools by muse/mcp.py
+3
observe/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Observe - System observation and recording utilities.""" 2 5 3 6 __all__ = []
+3
observe/categories/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Category prompts and formatters for screen description. 2 5 3 6 This package contains:
+3
observe/categories/meeting.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Formatter for meeting category content. 2 5 3 6 Renders meeting analysis JSON to rich markdown with participants and screen share.
+6 -1
observe/categories/tmux.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Formatter for tmux category content. 2 5 3 6 Renders tmux terminal capture to markdown with pane contents. ··· 33 36 # Session and window header 34 37 session = content.get("session", "unknown") 35 38 window = content.get("window", {}) 36 - window_name = window.get("name", "unknown") if isinstance(window, dict) else "unknown" 39 + window_name = ( 40 + window.get("name", "unknown") if isinstance(window, dict) else "unknown" 41 + ) 37 42 38 43 lines.append(f"**Tmux** ({session}:{window_name})") 39 44 lines.append("")
+3
observe/describe.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """ 3 6 Describe screencast videos by detecting significant frame changes. 4 7
+3
observe/detect.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import threading 2 5 3 6 import numpy as np
+3
observe/diarize.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Speaker diarization using pyannote pipeline with embedding extraction. 2 5 3 6 This module provides speaker diarization (who spoke when) using the pyannote
+18 -1
observe/gnome/__init__.py
··· 1 - """GNOME-specific observation utilities.""" 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 4 + """GNOME-specific activity detection library.""" 5 + 6 + from observe.gnome.activity import ( 7 + get_idle_time_ms, 8 + get_monitor_geometries, 9 + is_power_save_active, 10 + is_screen_locked, 11 + ) 12 + 13 + __all__ = [ 14 + "get_idle_time_ms", 15 + "get_monitor_geometries", 16 + "is_power_save_active", 17 + "is_screen_locked", 18 + ]
+4 -39
observe/gnome/activity.py
··· 1 - """GNOME Shell and Mutter DBus interface primitives.""" 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 4 + """GNOME-specific activity detection using Mutter and GTK DBus APIs.""" 2 5 3 - import asyncio 4 - import logging 5 6 import os 6 7 7 8 import gi ··· 125 126 126 127 # Assign position labels using shared algorithm 127 128 return assign_monitor_positions(geometries) 128 - 129 - 130 - async def is_sink_muted() -> bool: 131 - """ 132 - Check if the default audio sink is muted using PulseAudio. 133 - 134 - Uses `pactl get-sink-mute @DEFAULT_SINK@` to query mute status. 135 - 136 - Returns: 137 - True if muted, False otherwise (including on error). 138 - """ 139 - logger = logging.getLogger(__name__) 140 - try: 141 - proc = await asyncio.create_subprocess_exec( 142 - "pactl", 143 - "get-sink-mute", 144 - "@DEFAULT_SINK@", 145 - stdout=asyncio.subprocess.PIPE, 146 - stderr=asyncio.subprocess.PIPE, 147 - ) 148 - stdout, stderr = await proc.communicate() 149 - 150 - if proc.returncode != 0: 151 - stderr_text = stderr.decode().strip() if stderr else "" 152 - logger.warning(f"pactl failed (rc={proc.returncode}): {stderr_text}") 153 - return False 154 - 155 - output = stdout.decode().strip() 156 - return "Mute: yes" in output 157 - 158 - except FileNotFoundError: 159 - logger.warning("pactl not found, assuming unmuted") 160 - return False 161 - except Exception as e: 162 - logger.warning(f"Error checking sink mute status: {e}") 163 - return False
+3
observe/hear.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Audio recording utilities for observe package.""" 2 5 3 6 from __future__ import annotations
+4
observe/linux/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 4 + """Linux desktop observation using XDG Portal and PipeWire."""
+44
observe/linux/audio.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 4 + """Linux audio utilities using PulseAudio/PipeWire.""" 5 + 6 + import asyncio 7 + import logging 8 + 9 + logger = logging.getLogger(__name__) 10 + 11 + 12 + async def is_sink_muted() -> bool: 13 + """ 14 + Check if the default audio sink is muted using PulseAudio. 15 + 16 + Uses `pactl get-sink-mute @DEFAULT_SINK@` to query mute status. 17 + 18 + Returns: 19 + True if muted, False otherwise (including on error). 20 + """ 21 + try: 22 + proc = await asyncio.create_subprocess_exec( 23 + "pactl", 24 + "get-sink-mute", 25 + "@DEFAULT_SINK@", 26 + stdout=asyncio.subprocess.PIPE, 27 + stderr=asyncio.subprocess.PIPE, 28 + ) 29 + stdout, stderr = await proc.communicate() 30 + 31 + if proc.returncode != 0: 32 + stderr_text = stderr.decode().strip() if stderr else "" 33 + logger.warning(f"pactl failed (rc={proc.returncode}): {stderr_text}") 34 + return False 35 + 36 + output = stdout.decode().strip() 37 + return "Mute: yes" in output 38 + 39 + except FileNotFoundError: 40 + logger.warning("pactl not found, assuming unmuted") 41 + return False 42 + except Exception as e: 43 + logger.warning(f"Error checking sink mute status: {e}") 44 + return False
+10 -4
observe/linux/observer.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """ 3 6 Unified observer for audio and screencast capture. 4 7 ··· 26 29 from dbus_next.aio import MessageBus 27 30 from dbus_next.constants import BusType 28 31 29 - from observe.gnome.dbus import ( 32 + from observe.gnome.activity import ( 30 33 get_idle_time_ms, 31 34 is_power_save_active, 32 35 is_screen_locked, 33 - is_sink_muted, 34 36 ) 35 - from observe.gnome.screencast import Screencaster, StreamInfo 36 37 from observe.hear import AudioRecorder 38 + from observe.linux.audio import is_sink_muted 39 + from observe.linux.screencast import Screencaster, StreamInfo 37 40 from observe.tmux.capture import TmuxCapture, write_captures_jsonl 38 41 from think.callosum import CallosumConnection 39 42 from think.utils import day_path, setup_cli ··· 532 535 new_mode = await self.check_activity_status() 533 536 534 537 # Check for GStreamer failure mid-recording 535 - if self.current_mode == MODE_SCREENCAST and not self.screencaster.is_healthy(): 538 + if ( 539 + self.current_mode == MODE_SCREENCAST 540 + and not self.screencaster.is_healthy() 541 + ): 536 542 logger.warning("Screencast recording failed, stopping gracefully") 537 543 stopped_streams = await self.screencaster.stop() 538 544
+4 -1
observe/linux/screencast.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """ 2 5 Portal-based multi-monitor screencast recording. 3 6 ··· 24 27 from dbus_next.aio import MessageBus 25 28 from dbus_next.constants import BusType 26 29 27 - from observe.gnome.dbus import get_monitor_geometries 30 + from observe.gnome.activity import get_monitor_geometries 28 31 29 32 # Workaround for dbus-next issue #122: portal has properties with hyphens 30 33 # (e.g., "power-saver-enabled") which violate strict D-Bus naming validation.
+3
observe/macos/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """macOS-specific observation utilities using ScreenCaptureKit."""
+3
observe/macos/activity.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """macOS system activity detection using PyObjC. 2 5 3 6 This module mirrors the GNOME dbus.py structure, providing activity detection
+5 -2
observe/macos/observer.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """ 3 6 macOS observer for audio and screencast capture using ScreenCaptureKit. 4 7 ··· 60 63 self.start_at_mono = time.monotonic() # Monotonic for elapsed calculations 61 64 self.capture_running = False 62 65 63 - # Multi-display tracking (similar to GNOME observer) 66 + # Multi-display tracking (similar to Linux observer) 64 67 self.current_displays: list[DisplayInfo] = [] 65 68 self.current_audio: AudioInfo | None = None 66 69 self.pending_finalization: list[tuple[str, str]] | None = None ··· 143 146 Check if audio file has enough voice activity to save. 144 147 145 148 Decodes the m4a file and applies the same 3-chunk RMS threshold 146 - logic as GNOME observer uses for real-time audio. 149 + logic as Linux observer uses for real-time audio. 147 150 148 151 Args: 149 152 audio_path: Path to the m4a audio file
+3
observe/macos/screencapture.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """ScreenCaptureKit integration via sck-cli subprocess. 2 5 3 6 This module manages the sck-cli subprocess lifecycle for video and audio capture
+5 -2
observe/observer.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Unified observer entry point with platform detection. 2 5 3 6 Detects the current platform and delegates to the appropriate ··· 12 15 13 16 Detects the current platform and calls the appropriate observer: 14 17 - macOS (darwin): observe.macos.observer 15 - - Linux: observe.gnome.observer 18 + - Linux: observe.linux.observer 16 19 17 20 All command-line arguments are passed through to the platform-specific 18 21 implementation via its main() function. ··· 22 25 if platform == "darwin": 23 26 from observe.macos.observer import main as platform_main 24 27 elif platform == "linux": 25 - from observe.gnome.observer import main as platform_main 28 + from observe.linux.observer import main as platform_main 26 29 else: 27 30 print( 28 31 f"Error: Observer not available for platform '{platform}'", file=sys.stderr
+3
observe/plaud.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """ 3 6 plaud.py — Sync Plaud audio files to local directory. 4 7
+3
observe/revai.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 import argparse 3 6 import json 4 7 import logging
+3
observe/screen.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """ 3 6 Screen analysis formatter for indexing and clustering. 4 7
+3
observe/see.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 from pathlib import Path
+3
observe/sense.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """File-based processor dispatcher for observe subsystem. 3 6 4 7 Watches day directories for new files and spawns appropriate handler processes,
+3
observe/tmux/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tmux terminal capture for observe package.""" 2 5 3 6 from observe.tmux.capture import (
+57 -36
observe/tmux/capture.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tmux terminal capture library. 2 5 3 6 Provides functions for capturing tmux session content, designed for use 4 - by the GNOME observer for fallback capture when screen is idle. 7 + by the Linux observer for fallback capture when screen is idle. 5 8 """ 6 9 7 10 import hashlib ··· 103 106 Returns: 104 107 List of dicts with 'session' and 'activity' keys. 105 108 """ 106 - output = run_tmux_command([ 107 - "list-clients", 108 - "-F", "#{client_session} #{client_activity}", 109 - ]) 109 + output = run_tmux_command( 110 + [ 111 + "list-clients", 112 + "-F", 113 + "#{client_session} #{client_activity}", 114 + ] 115 + ) 110 116 if not output: 111 117 return [] 112 118 ··· 136 142 137 143 def get_windows(self, session: str) -> list[WindowInfo]: 138 144 """Get all windows for a session.""" 139 - output = run_tmux_command([ 140 - "list-windows", 141 - "-t", session, 142 - "-F", "#{window_active} #{window_id} #{window_index} #{window_name}", 143 - ]) 145 + output = run_tmux_command( 146 + [ 147 + "list-windows", 148 + "-t", 149 + session, 150 + "-F", 151 + "#{window_active} #{window_id} #{window_index} #{window_name}", 152 + ] 153 + ) 144 154 if not output: 145 155 return [] 146 156 ··· 154 164 155 165 active_str, window_id, index_str, name = parts 156 166 try: 157 - windows.append(WindowInfo( 158 - id=window_id, 159 - index=int(index_str), 160 - name=name, 161 - active=(active_str == "1"), 162 - )) 167 + windows.append( 168 + WindowInfo( 169 + id=window_id, 170 + index=int(index_str), 171 + name=name, 172 + active=(active_str == "1"), 173 + ) 174 + ) 163 175 except ValueError: 164 176 continue 165 177 ··· 167 179 168 180 def get_panes(self, window_id: str) -> list[PaneInfo]: 169 181 """Get all panes for a window with layout info.""" 170 - output = run_tmux_command([ 171 - "list-panes", 172 - "-t", window_id, 173 - "-F", "#{pane_id} #{pane_index} #{pane_left} #{pane_top} #{pane_width} #{pane_height} #{pane_active}", 174 - ]) 182 + output = run_tmux_command( 183 + [ 184 + "list-panes", 185 + "-t", 186 + window_id, 187 + "-F", 188 + "#{pane_id} #{pane_index} #{pane_left} #{pane_top} #{pane_width} #{pane_height} #{pane_active}", 189 + ] 190 + ) 175 191 if not output: 176 192 return [] 177 193 ··· 184 200 continue 185 201 186 202 try: 187 - panes.append(PaneInfo( 188 - id=parts[0], 189 - index=int(parts[1]), 190 - left=int(parts[2]), 191 - top=int(parts[3]), 192 - width=int(parts[4]), 193 - height=int(parts[5]), 194 - active=(parts[6] == "1"), 195 - )) 203 + panes.append( 204 + PaneInfo( 205 + id=parts[0], 206 + index=int(parts[1]), 207 + left=int(parts[2]), 208 + top=int(parts[3]), 209 + width=int(parts[4]), 210 + height=int(parts[5]), 211 + active=(parts[6] == "1"), 212 + ) 213 + ) 196 214 except ValueError: 197 215 continue 198 216 ··· 200 218 201 219 def capture_pane(self, pane_id: str) -> str: 202 220 """Capture visible pane content with ANSI escape codes.""" 203 - output = run_tmux_command([ 204 - "capture-pane", 205 - "-p", # Print to stdout 206 - "-e", # Include escape sequences (ANSI codes) 207 - "-t", pane_id, 208 - ]) 221 + output = run_tmux_command( 222 + [ 223 + "capture-pane", 224 + "-p", # Print to stdout 225 + "-e", # Include escape sequences (ANSI codes) 226 + "-t", 227 + pane_id, 228 + ] 229 + ) 209 230 return output if output else "" 210 231 211 232 def capture_session(self, session: str) -> CaptureResult | None:
+3
observe/transcribe.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Transcribe audio files using Gemini with speaker diarization.""" 2 5 3 6 from __future__ import annotations
+3
observe/utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Utilities for working with screencasts and video files.""" 2 5 3 6 import json
+3 -3
pyproject.toml
··· 8 8 description = "Navigate Intelligently - A collection of utilities for multimodal navigation and analysis" 9 9 readme = "README.md" 10 10 requires-python = ">=3.10" 11 - license = {text = "MIT"} 11 + license = {text = "AGPL-3.0-only"} 12 12 authors = [ 13 13 {name = "Jer+AI", email = "jeremie.miller@gmail.com"} 14 14 ] 15 15 classifiers = [ 16 16 "Development Status :: 3 - Alpha", 17 17 "Intended Audience :: Developers", 18 - "License :: OSI Approved :: MIT License", 18 + "License :: OSI Approved :: GNU Affero General Public License v3", 19 19 "Operating System :: POSIX :: Linux", 20 20 "Programming Language :: Python :: 3", 21 21 "Programming Language :: Python :: 3.10", ··· 112 112 think-callosum = "think.callosum:main" 113 113 think-messages = "think.messages:main" 114 114 observer = "observe.observer:main" 115 - observe-gnome = "observe.gnome.observer:main" 115 + observe-linux = "observe.linux.observer:main" 116 116 observe-macos = "observe.macos.observer:main" 117 117 observe-transcribe = "observe.transcribe:main" 118 118 observe-describe = "observe.describe:main"
+2
tests/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc
+3
tests/agents_stub.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import sys 2 5 import types 3 6 from types import SimpleNamespace
+3
tests/conftest.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import os 3 6 import sys
+3
tests/integration/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration tests for solstone. 2 5 3 6 These tests are separate from unit tests and test the complete system integration.
+3
tests/integration/conftest.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Configuration and fixtures for integration tests.""" 2 5 3 6 import os
+3
tests/integration/test_anthropic_backend.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration test for Anthropic backend with real API calls.""" 2 5 3 6 import json
+3
tests/integration/test_app_tool_discovery.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration tests for app-level MCP tool discovery.""" 2 5 3 6 import os
+3
tests/integration/test_batch.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration tests for GeminiBatch with real Gemini API.""" 2 5 3 6 import asyncio
+3
tests/integration/test_callosum.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration tests for the Callosum message bus. 2 5 3 6 These tests use real servers, sockets, and I/O to validate core flows.
+3
tests/integration/test_claude_backend.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration test for Claude backend with SDK integration.""" 2 5 3 6 import json
+3
tests/integration/test_cortex.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration tests for the Cortex agent system with Callosum.""" 2 5 3 6 import json
+3
tests/integration/test_example_integration.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Example integration test to demonstrate the structure.""" 2 5 3 6 import pytest
+3
tests/integration/test_gemini_generate.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration test for gemini_generate function with real API calls.""" 2 5 3 6 import json
+3
tests/integration/test_google_backend.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration test for Google backend with real API calls.""" 2 5 3 6 import json
+3
tests/integration/test_mcp_server.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration tests for MCP server with full protocol testing.""" 2 5 3 6 import asyncio
+3
tests/integration/test_openai_backend.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Integration test for OpenAI backend with real API calls.""" 2 5 3 6 import json
+3
tests/test_action_logging.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Test audit logging for MCP entity tool actions.""" 2 5 3 6 import json
+3
tests/test_agents_history.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for agents conversation history functions.""" 2 5 3 6 from muse.agents import format_tool_summary, parse_agent_events_to_turns
+3
tests/test_agents_ndjson.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for NDJSON-only input in muse.agents.""" 2 5 3 6 import asyncio
+3
tests/test_anthropic.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import asyncio 2 5 import importlib 3 6 import json
+3
tests/test_app_agents.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for app agent discovery and loading.""" 2 5 3 6 import json
+3
tests/test_apps.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for Convey app endpoints. 2 5 3 6 Tests that all apps with workspace.html can be accessed via /app/{app_name}.
+3
tests/test_batch.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for the GeminiBatch async batch processor.""" 2 5 3 6 import asyncio
+3
tests/test_callosum.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Unit tests for the Callosum message bus. 2 5 3 6 These tests use mocks to test logic in isolation without real I/O.
+3
tests/test_cluster.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 3 6 from think.utils import day_path
+3
tests/test_cluster_full.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import os 3 6 import shutil
+3
tests/test_config.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for journal configuration utilities.""" 2 5 3 6 import json
+3
tests/test_convey_utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import json 2 5 import os 3 6
+3
tests/test_cortex.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for the file-based Cortex agent manager.""" 2 5 3 6 import json
+3
tests/test_cortex_client.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for cortex_client module with Callosum.""" 2 5 3 6 import json
+3
tests/test_describe_config.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for observe/describe.py category discovery and configuration.""" 2 5 3 6 from observe import describe as describe_module
+3
tests/test_detect_transcript.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import json 3 6
+3
tests/test_dream_full.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import shutil 3 6 from pathlib import Path
+3
tests/test_entities.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for facet-scoped entity utilities.""" 2 5 3 6 import os
+3
tests/test_entity_agents.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for entity detection and review agent configurations.""" 2 5 3 6 import os
+3
tests/test_entity_validation.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for entity type validation.""" 2 5 3 6 import pytest
+3
tests/test_events.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import json 2 5 3 6
+3
tests/test_facet_news.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for facet news utilities.""" 2 5 3 6 import json
+3
tests/test_facets.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for think.facets module.""" 2 5 3 6 from pathlib import Path
+3
tests/test_formatters.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for the formatters framework.""" 2 5 3 6 import json
+3
tests/test_gemini_generate.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for the gemini_generate wrapper function.""" 2 5 3 6 import json
+3
tests/test_get_insights.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import os 3 6 import tempfile
+3
tests/test_get_raw_file.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 3 6 from think.utils import day_path
+3
tests/test_google.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import asyncio 2 5 import importlib 3 6 import json
+3
tests/test_google_thinking.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import asyncio 2 5 import importlib 3 6 import json
+3
tests/test_importer.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import datetime as dt 2 5 import importlib 3 6 import json
+3
tests/test_importer_jsonl.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for think.importer JSONL format writing.""" 2 5 3 6 import json
+3
tests/test_importer_utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for think.importer_utils module.""" 2 5 3 6 import json
+3
tests/test_insight_full.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import json 3 6 import os
+3
tests/test_insight_scan_day.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import os 3 6 import shutil
+3
tests/test_journal_index.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for the unified journal index.""" 2 5 3 6 import json
+3
tests/test_journal_stats.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import json 3 6
+3
tests/test_load_transcript.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for observe.hear.load_transcript() function.""" 2 5 3 6 import json
+3
tests/test_mcp_tools.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from unittest.mock import patch 2 5 3 6 from apps.entities import tools as entity_tools
+3
tests/test_models.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for think.models module.""" 2 5 3 6 from think.models import (
+3
tests/test_observe_utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for observe/utils.py functions.""" 2 5 3 6 from observe.utils import (
+3
tests/test_openai.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import asyncio 2 5 import importlib 3 6 import json
+3
tests/test_package_api.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 # Test removed - checking hasattr for package exports is not useful
+3
tests/test_parse_time_range.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 from datetime import datetime 3 6
+3
tests/test_planner.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import sys 3 6 from types import SimpleNamespace
+3
tests/test_runner.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for think.runner and logs tract integration.""" 2 5 3 6 import os
+3
tests/test_screen_formatter.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for observe.screen formatter module.""" 2 5 3 6 from pathlib import Path
+3
tests/test_see.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for observe.see utilities.""" 2 5 3 6 import pytest
+3
tests/test_sense.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for observe.sense module.""" 2 5 3 6 import subprocess
+3
tests/test_supervisor.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import importlib 2 5 import io 3 6 import logging
+3
tests/test_supervisor_schedule.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Test supervisor scheduling functionality.""" 2 5 3 6 import asyncio
+3
tests/test_template_substitution.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for template variable substitution in load_prompt.""" 2 5 3 6 import json
+3
tests/test_think_utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for think.utils module.""" 2 5 3 6 import json
+3
tests/test_transcribe.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Tests for observe.transcribe validation logic.""" 2 5 3 6 import json
+3
tests/test_utils_mcp_http.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """Tests for HTTP MCP integration in utils.py.""" 3 6 4 7 import sys
+3
think/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from .detect_created import detect_created 2 5 from .detect_transcript import detect_transcript_json, detect_transcript_segment 3 6 from .planner import generate_plan
+3
think/batch.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """ 2 5 Async batch processing for Gemini API requests. 3 6
+3
think/callosum.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Callosum: WebSocket-like broadcast message bus over Unix domain sockets. 2 5 3 6 Provides real-time event distribution across solstone services using a simple
+3
think/cluster.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import argparse 2 5 import os 3 6 import re
+3
think/detect_created.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Media file metadata detection utilities.""" 2 5 3 6 from __future__ import annotations
+3
think/detect_transcript.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Transcript segmentation utilities using Gemini.""" 2 5 3 6 from __future__ import annotations
+3
think/dream.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import argparse 2 5 import logging 3 6 import os
+3
think/entities.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Facet-scoped entity utilities for detected and attached entities.""" 2 5 3 6 import hashlib
+3
think/events.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Event formatting and utilities for the journal. 2 5 3 6 This module provides:
+3
think/facets.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Facet-specific utilities and tooling for the think module.""" 2 5 3 6 import json
+3
think/formatters.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Formatters framework for JSONL and Markdown files. 2 5 3 6 This module provides a registry-based system for converting structured files
+3
think/importer.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import argparse 2 5 import datetime as dt 3 6 import json
+3
think/importer_utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Utility functions for import operations. 2 5 3 6 This module contains reusable logic for managing imports in the journal,
+3
think/indexer/__init__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Indexer package for journal content. 2 5 3 6 This module provides the unified journal index for all content types.
+3
think/indexer/__main__.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Main entry point for the think.indexer package when run as a module.""" 2 5 3 6 from .cli import main
+3
think/indexer/cli.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """CLI functionality for the indexer.""" 2 5 3 6 import argparse
+3
think/indexer/journal.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Unified journal index for all content types. 2 5 3 6 This module provides a single FTS5 index over all journal content:
+3
think/insight.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import argparse 2 5 import json 3 6 import os
+3
think/insights.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Semantic markdown chunking formatter. 2 5 3 6 This module provides semantic chunking for markdown files, breaking documents
+3
think/journal_stats.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import argparse 2 5 import json 3 6 import logging
+3
think/manage.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 """Interactive service manager for solstone supervisor. 2 5 3 6 Connects to the Callosum message bus to display real-time service status
+3
think/models.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import inspect 2 5 import json 3 6 import os
+3
think/planner.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import argparse 2 5 import asyncio 3 6 import logging
+3
think/runner.py
··· 1 1 #!/usr/bin/env python3 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2026 sol pbc 4 + 2 5 """Unified process spawning and lifecycle management utilities. 3 6 4 7 All subprocess output is automatically logged to:
+3
think/solstone.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 import argparse 2 5 import importlib 3 6 import logging
+3
think/supervisor.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import argparse
+3
think/utils.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 1 4 from __future__ import annotations 2 5 3 6 import argparse